Merge authors: James Hunt (jamesodhunt) Steve Langasek (vorlon) Related merge proposals: https://code.launchpad.net/~jamesodhunt/upstart/bug-980917-reworked/+merge/118132 proposed by: James Hunt (jamesodhunt) review: Disapprove - Steve Langasek (vorlon) https://code.launchpad.net/~jamesodhunt/upstart/bug-980917/+merge/117863 proposed by: James Hunt (jamesodhunt) review: Disapprove - Steve Langasek (vorlon) ------------------------------------------------------------ revno: 1375 [merge] committer: Steve Langasek <[email protected]> branch nick: upstream timestamp: Mon 2012-08-06 18:07:52 -0700 message: Land fix for /dev/pts mounting modified: ChangeLog init/main.c init/system.c init/system.h
-- lp:upstart https://code.launchpad.net/~upstart-devel/upstart/trunk Your team Upstart Reviewers is subscribed to branch lp:upstart. To unsubscribe from this branch go to https://code.launchpad.net/~upstart-devel/upstart/trunk/+edit-subscription
=== modified file 'ChangeLog' --- ChangeLog 2012-07-31 08:39:57 +0000 +++ ChangeLog 2012-08-03 15:47:59 +0000 @@ -1,3 +1,11 @@ +2012-08-03 James Hunt <[email protected]> + + * init/main.c:main(): Handle hostile initramfs-less environments by + calling umask and creating required device nodes as early as possible. + * init/system.c: New functions to simplify code: + - system_mknod() + - system_check_file() + 2012-07-31 James Hunt <[email protected]> [ Eric S. Raymond <[email protected]> ] === modified file 'init/main.c' --- init/main.c 2011-12-15 16:26:34 +0000 +++ init/main.c 2012-08-03 15:47:59 +0000 @@ -28,6 +28,7 @@ #include <sys/ioctl.h> #include <sys/reboot.h> #include <sys/resource.h> +#include <sys/mount.h> #include <errno.h> #include <stdio.h> @@ -192,6 +193,8 @@ #ifndef DEBUG if (use_session_bus == FALSE) { + int needs_devtmpfs = 0; + /* Check we're root */ if (getuid ()) { nih_fatal (_("Need to be root")); @@ -236,6 +239,70 @@ */ setsid (); + /* Allow devices to be created with the actual perms + * specified. + */ + (void)umask (0); + + /* Check if key devices already exist; if they do, + * we should assume we don't need to mount /dev. + */ + if (system_check_file ("/dev/null", S_IFCHR, makedev (1, 3)) < 0) + needs_devtmpfs = 1; + + if (system_check_file ("/dev/console", S_IFCHR, makedev (5, 1)) < 0) + needs_devtmpfs = 1; + + if (system_check_file ("/dev/tty", S_IFCHR, makedev (5, 0)) < 0) + needs_devtmpfs = 1; + + if (system_check_file ("/dev/kmsg", S_IFCHR, makedev (1, 11)) < 0) + needs_devtmpfs = 1; + + if (system_check_file ("/dev/ptmx", S_IFCHR, makedev (5, 2)) < 0) + needs_devtmpfs = 1; + + if (system_check_file ("/dev/pts", S_IFDIR, 0) < 0) + needs_devtmpfs = 1; + + if (needs_devtmpfs) { + if (system_mount ("devtmpfs", "/dev", (MS_NOEXEC | MS_NOSUID)) < 0) { + NihError *err; + + err = nih_error_get (); + nih_error ("%s: %s", _("Unable to mount /dev filesystem"), + err->message); + nih_free (err); + } + + /* Required to exist before /dev/pts accessed */ + system_mknod ("/dev/ptmx", (S_IFCHR | 0666), makedev (5, 2)); + + if (mkdir ("/dev/pts", 0755) < 0 && errno != EEXIST) + nih_error ("%s: %s", _("Cannot create directory"), "/dev/pts"); + } + + if (system_mount ("devpts", "/dev/pts", (MS_NOEXEC | MS_NOSUID)) < 0) { + NihError *err; + + err = nih_error_get (); + nih_error ("%s: %s", _("Unable to mount /dev/pts filesystem"), + err->message); + nih_free (err); + } + + /* These devices must exist, but we have to have handled the /dev + * check (and possible mount) prior to considering + * creating them. And yet, if /dev is not available from + * the outset and an error occurs, we are unable to report it, + * hence these checks are performed as early as is + * feasible. + */ + system_mknod ("/dev/null", (S_IFCHR | 0666), makedev (1, 3)); + system_mknod ("/dev/tty", (S_IFCHR | 0666), makedev (5, 0)); + system_mknod ("/dev/console", (S_IFCHR | 0600), makedev (5, 1)); + system_mknod ("/dev/kmsg", (S_IFCHR | 0600), makedev (1, 11)); + /* Set the standard file descriptors to the ordinary console device, * resetting it to sane defaults unless we're inheriting from another * init process which we know left it in a sane state. @@ -271,9 +338,10 @@ /* Mount the /proc and /sys filesystems, which are pretty much * essential for any Linux system; not to mention used by - * ourselves. + * ourselves. Also mount /dev/pts to allow CONSOLE_LOG + * to function if booted in an initramfs-less environment. */ - if (system_mount ("proc", "/proc") < 0) { + if (system_mount ("proc", "/proc", (MS_NODEV | MS_NOEXEC | MS_NOSUID)) < 0) { NihError *err; err = nih_error_get (); @@ -282,7 +350,7 @@ nih_free (err); } - if (system_mount ("sysfs", "/sys") < 0) { + if (system_mount ("sysfs", "/sys", (MS_NODEV | MS_NOEXEC | MS_NOSUID)) < 0) { NihError *err; err = nih_error_get (); @@ -290,6 +358,7 @@ err->message); nih_free (err); } + } else { nih_log_set_priority (NIH_LOG_DEBUG); nih_debug ("Running with UID %d as PID %d (PPID %d)", === modified file 'init/system.c' --- init/system.c 2011-12-09 14:07:11 +0000 +++ init/system.c 2012-08-03 15:47:59 +0000 @@ -164,9 +164,10 @@ /** * system_mount: * @type: filesystem type, - * @dir: mountpoint. + * @dir: mountpoint, + * @flags: mount flags. * - * Mount the kernel filesystem @type at @dir, if not already mounted. This + * Mount the kernel filesystem @type at @dir with @flags, if not already mounted. This * is used to ensure that the proc and sysfs filesystems are always * available. * @@ -177,7 +178,8 @@ **/ int system_mount (const char *type, - const char *dir) + const char *dir, + unsigned long flags) { nih_local char *parent = NULL; char * ptr; @@ -206,9 +208,65 @@ return 0; /* Mount the filesystem */ - if (mount ("none", dir, type, - MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL) < 0) + if (mount ("none", dir, type, flags, NULL) < 0) nih_return_system_error (-1); return 0; } + +/** + * system_mknod: + * + * @path: full path, + * @mode: mode to create device with, + * @dev: device major and minor numbers. + * + * Create specified device. + * + * Note that depending on the device, if an error occurs + * it may not be reportable, hence no return value, + * but an attempt to display an error. + **/ +void +system_mknod (const char *path, mode_t mode, dev_t dev) +{ + nih_assert (path); + + if (mknod (path, mode, dev) < 0 && errno != EEXIST) + nih_error ("%s: %s", _("Unable to create device"), path); +} + +/** + * system_check_file: + * + * @path: full path, + * @type: file type, + * @dev: device major and minor numbers (only checked for character and + * block devices). + * + * Perform checks on specified file. + * + * Returns: 0 if device exists and has the specified @path, + * @type and @dev attributes, else -1. + **/ +int +system_check_file (const char *path, mode_t type, dev_t dev) +{ + struct stat statbuf; + int ret; + + nih_assert (path); + + ret = stat (path, &statbuf); + + if (ret < 0 || ! ((statbuf.st_mode & S_IFMT) == type)) + return -1; + + if (type == S_IFCHR || type == S_IFBLK) { + if (major (statbuf.st_rdev) != major (dev) + || minor (statbuf.st_rdev) != minor (dev)) + return -1; + } + + return 0; +} === modified file 'init/system.h' --- init/system.h 2011-05-12 20:42:28 +0000 +++ init/system.h 2012-08-03 15:47:59 +0000 @@ -35,7 +35,13 @@ int system_setup_console (ConsoleType type, int reset) __attribute__ ((warn_unused_result)); -int system_mount (const char *type, const char *dir) +int system_mount (const char *type, const char *dir, + unsigned long flags) + __attribute__ ((warn_unused_result)); + +void system_mknod (const char *path, mode_t mode, dev_t dev); + +int system_check_file (const char *path, mode_t type, dev_t dev) __attribute__ ((warn_unused_result)); NIH_END_EXTERN
-- upstart-devel mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/upstart-devel
