summaryrefslogtreecommitdiffstats
path: root/login-utils/sulogin-consoles.c
diff options
context:
space:
mode:
authorWerner Fink2016-02-11 13:35:26 +0100
committerKarel Zak2016-02-12 11:19:21 +0100
commitcde7699c27ff22bed8d554d50e10a42ec0dba6d8 (patch)
treeb0730ea20d74c823c1f5025d9c7ad77740b38829 /login-utils/sulogin-consoles.c
parenttests: add test for loop option in fstab (diff)
downloadkernel-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.c53
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;