diff options
author | Werner Fink | 2016-02-11 13:35:26 +0100 |
---|---|---|
committer | Karel Zak | 2016-02-12 11:19:21 +0100 |
commit | cde7699c27ff22bed8d554d50e10a42ec0dba6d8 (patch) | |
tree | b0730ea20d74c823c1f5025d9c7ad77740b38829 /login-utils/sulogin-consoles.c | |
parent | tests: add test for loop option in fstab (diff) | |
download | kernel-qcow2-util-linux-cde7699c27ff22bed8d554d50e10a42ec0dba6d8.tar.gz kernel-qcow2-util-linux-cde7699c27ff22bed8d554d50e10a42ec0dba6d8.tar.xz kernel-qcow2-util-linux-cde7699c27ff22bed8d554d50e10a42ec0dba6d8.zip |
sulogin: avoid shared memory area usemask but use waitid() for childs
This small patch improves the console detection code and also avoids not
existing device nodes due strdup() which is used in canonicalize_path().
Beside this now the code for emergeny mount does work if enabled at
configure time.
Signed-off-by: Werner Fink <werner@suse.de>
Diffstat (limited to 'login-utils/sulogin-consoles.c')
-rw-r--r-- | login-utils/sulogin-consoles.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/login-utils/sulogin-consoles.c b/login-utils/sulogin-consoles.c index bc55e9cb6..fe8eab15d 100644 --- a/login-utils/sulogin-consoles.c +++ b/login-utils/sulogin-consoles.c @@ -36,8 +36,9 @@ # include <linux/serial.h> # include <linux/major.h> #endif -#include <fcntl.h> #include <dirent.h> +#include <errno.h> +#include <fcntl.h> #include <unistd.h> #ifdef USE_SULOGIN_EMERGENCY_MOUNT @@ -226,6 +227,8 @@ dev_t devattr(const char *tty) /* * Search below /dev for the character device in `dev_t comparedev' variable. + * Note that realpath(3) is used here to avoid not existent devices due the + * strdup(3) used in our canonicalize_path()! */ static #ifdef __GNUC__ @@ -233,16 +236,28 @@ __attribute__((__nonnull__,__malloc__,__hot__)) #endif char* scandev(DIR *dir, dev_t comparedev) { + char path[PATH_MAX]; char *name = NULL; struct dirent *dent; - int fd; + int len, fd; DBG(dbgprint("scanning /dev for %u:%u", major(comparedev), minor(comparedev))); + /* + * Try udev links on character devices first. + */ + if ((len = snprintf(path, sizeof(path), + "/dev/char/%u:%u", major(comparedev), minor(comparedev))) > 0 && + (size_t)len < sizeof(path)) { + + name = realpath(path, NULL); + if (name) + goto out; + } + fd = dirfd(dir); rewinddir(dir); while ((dent = readdir(dir))) { - char path[PATH_MAX]; struct stat st; #ifdef _DIRENT_HAVE_D_TYPE @@ -255,17 +270,33 @@ char* scandev(DIR *dir, dev_t comparedev) continue; if (comparedev != st.st_rdev) continue; - if ((size_t)snprintf(path, sizeof(path), "/dev/%s", dent->d_name) >= sizeof(path)) + if ((len = snprintf(path, sizeof(path), "/dev/%s", dent->d_name)) < 0 || + (size_t)len >= sizeof(path)) continue; -#ifdef USE_SULOGIN_EMERGENCY_MOUNT - if (emergency_flags & MNT_DEVTMPFS) - mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev); -#endif - name = canonicalize_path(path); - break; + name = realpath(path, NULL); + if (name) + goto out; } +#ifdef USE_SULOGIN_EMERGENCY_MOUNT + /* + * There was no /dev mounted hence and no device was found hence we create our own. + */ + if (!name && (emergency_flags & MNT_DEVTMPFS)) { + + if ((len = snprintf(path, sizeof(path), + "/dev/tmp-%u:%u", major(comparedev), minor(comparedev))) < 0 || + (size_t)len >= sizeof(path)) + goto out; + + if (mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev) < 0 && errno != EEXIST) + goto out; + + name = realpath(path, NULL); + } +#endif +out: return name; } @@ -307,7 +338,7 @@ int append_console(struct list_head *consoles, const char *name) tail->flags = 0; tail->fd = -1; tail->id = last ? last->id + 1 : 0; - tail->pid = 0; + tail->pid = -1; memset(&tail->tio, 0, sizeof(tail->tio)); return 0; |