[Branch ~upstart-devel/upstart/trunk] Rev 1375: Land fix for /dev/pts mounting

Serge Hallyn serge.hallyn at canonical.com
Tue Aug 7 01:32:27 UTC 2012


Quoting noreply at launchpad.net (noreply at launchpad.net):
> 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 <steve.langasek at canonical.com>
> 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  <james.hunt at ubuntu.com>
> +
> +	* 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  <james.hunt at ubuntu.com>
>  
>  	[ Eric S. Raymond <esr at thyrsus.com> ]
> 
> === 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;

IIUC this will be a problem for lxc containers, where /dev/console is set
up before upstart begins (to be a symlink to /dev/lxc/console which itself
is a bind mount from devpts.)

> +		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
> upstart-devel at lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/upstart-devel




More information about the upstart-devel mailing list