ueventd: relabel block devices nodes when processing subsequent add events
There is a race in ueventd's coldboot procedure that permits creation of device block nodes before platform devices are registered. This happens when the kernel sends events for adding block devices during ueventd's coldboot /sys walk. In this case the device node links used to compute the SELinux context are not known and the node is created under the generic context: u:object_r:block_device:s0. A second add event for block device nodes is triggered after the platform devices are handled by ueventd and the SELinux context is correctly computed but the mknod call fails because the node already exists. This patch handles this error case and updates the node's security context. The race is introduced by the uevent sent from the sdcard device probe function. The issue appears when this uevent is triggered during ueventd's coldboot procedure but before the /sys/devices recursive walk reached the corresponding sdcard platform device path. The backtrace looks something like: 1. ueventd_main() 2. device_init() 3. coldboot("/sys/devices"); 4. do_coldboot() 5. handle_device_fd() 6. handle_device_event() 6.1 handle_block_device_event() 6.2 handle_platform_device_event() Because handle_device_fd() reads all events from the netlink socket it may handle the add events for the sdcard partition nodes send occasionally by the kernel during coldboot /sys walk procedure. If handle_device_event() continues with handle_block_device_event() before handle_platform_device_event() registers the sdcard platform device then handle_block_device_event() will create device nodes without knowing all block device symlinks (get_block_device_symlinks()): 1. handle_device(path=/dev/block/mmcblk0p3, links = NULL) 2. make_device(path=/dev/block/mmcblk0p3, links = NULL) 3. selabel_lookup_best_match(path=/dev/block/mmcblk0p3, links = NULL) returns the default context (u:object_r:block_device:s0) for /dev/block/mmcblk0p3 instead of more specific context like: u:object_r:boot_block_device:s0 4. setfscreatecon(u:object_r:block_device:s0) 5. mknod(/dev/block/mmcblk0p3) So the node is create with the wrong context. Afterwards the coldboot /sys walk continues and make_device() will be called with correct path and links. But even if the secontext is computed correctly this time it will not be applied to the device node because mknod() fails. I see this issue randomly appearing (one time in 10 reboots) on a Minnoboard Turbot with external sdcard as the boot device. BUG=28388946 Change-Id: I96e239af29d82b753e5d349b3ecefaad09edee87 Signed-off-by: Mihai Serban <mihai.serban@intel.com>
This commit is contained in:
parent
58505e17bb
commit
24a3cbfa73
|
@ -244,7 +244,11 @@ static void make_device(const char *path,
|
|||
|
||||
mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
|
||||
|
||||
selabel_lookup_best_match(sehandle, &secontext, path, links, mode);
|
||||
if (selabel_lookup_best_match(sehandle, &secontext, path, links, mode)) {
|
||||
ERROR("Device '%s' not created; cannot find SELinux label (%s)\n",
|
||||
path, strerror(errno));
|
||||
return;
|
||||
}
|
||||
setfscreatecon(secontext);
|
||||
|
||||
dev = makedev(major, minor);
|
||||
|
@ -254,14 +258,19 @@ static void make_device(const char *path,
|
|||
* racy. Fixing the gid race at least fixed the issue with system_server
|
||||
* opening dynamic input devices under the AID_INPUT gid. */
|
||||
setegid(gid);
|
||||
mknod(path, mode, dev);
|
||||
/* If the node already exists update its SELinux label to handle cases when
|
||||
* it was created with the wrong context during coldboot procedure. */
|
||||
if (mknod(path, mode, dev) && (errno == EEXIST)) {
|
||||
if (lsetfilecon(path, secontext)) {
|
||||
ERROR("Cannot set '%s' SELinux label on '%s' device (%s)\n",
|
||||
secontext, path, strerror(errno));
|
||||
}
|
||||
}
|
||||
chown(path, uid, -1);
|
||||
setegid(AID_ROOT);
|
||||
|
||||
if (secontext) {
|
||||
freecon(secontext);
|
||||
setfscreatecon(NULL);
|
||||
}
|
||||
freecon(secontext);
|
||||
setfscreatecon(NULL);
|
||||
}
|
||||
|
||||
static void add_platform_device(const char *path)
|
||||
|
|
Loading…
Reference in New Issue