From 370c860f748d149097710dc7952a64f627db9de7 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sat, 19 Apr 2014 13:22:35 -0400 Subject: [PATCH] implement a union to pad out file_handle Cases where name_to_handle_at is used allocated the full struct to be MAX_HANDLE_SZ, and assigned this size to handle_bytes. This is wrong since handle_bytes should describe the length of the flexible array member and not the whole struct. Define a union type which includes sufficient padding to allow assignment of MAX_HANDLE_SZ to be correct. --- src/libudev/libudev-monitor.c | 6 ++---- src/readahead/readahead-common.c | 6 ++---- src/shared/util.h | 6 ++++++ src/tmpfiles/tmpfiles.c | 11 ++++------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git src/libudev/libudev-monitor.c src/libudev/libudev-monitor.c index 3f7436b..0a2ab82 100644 --- src/libudev/libudev-monitor.c +++ src/libudev/libudev-monitor.c @@ -108,15 +108,13 @@ static struct udev_monitor *udev_monitor_new(struct udev *udev) /* we consider udev running when /dev is on devtmpfs */ static bool udev_has_devtmpfs(struct udev *udev) { - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ, }; int mount_id; _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX], *e; int r; - h = alloca(MAX_HANDLE_SZ); - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(AT_FDCWD, "/dev", h, &mount_id, 0); + r = name_to_handle_at(AT_FDCWD, "/dev", &h.handle, &mount_id, 0); if (r < 0) return false; diff --git src/readahead/readahead-common.c src/readahead/readahead-common.c index 5ffa88b..49679fc 100644 --- src/readahead/readahead-common.c +++ src/readahead/readahead-common.c @@ -75,7 +75,7 @@ int fs_on_ssd(const char *p) { if (major(st.st_dev) == 0) { _cleanup_fclose_ FILE *f = NULL; int mount_id; - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ, }; /* Might be btrfs, which exposes "ssd" as mount flag if it is on ssd. * @@ -83,9 +83,7 @@ int fs_on_ssd(const char *p) { * and then lookup the mount ID in mountinfo to find * the mount options. */ - h = alloca(MAX_HANDLE_SZ); - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(AT_FDCWD, p, h, &mount_id, AT_SYMLINK_FOLLOW); + r = name_to_handle_at(AT_FDCWD, p, &h.handle, &mount_id, AT_SYMLINK_FOLLOW); if (r < 0) return false; diff --git src/shared/util.h src/shared/util.h index 900f1cf..891848a 100644 --- src/shared/util.h +++ src/shared/util.h @@ -22,6 +22,7 @@ ***/ #include +#include #include #include #include @@ -883,3 +884,8 @@ int fd_warn_permissions(const char *path unsigned long personality_from_string(const char *p); const char *personality_to_string(unsigned long); + +union file_handle_union { + struct file_handle handle; + char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ]; +}; diff --git src/tmpfiles/tmpfiles.c src/tmpfiles/tmpfiles.c index 33e7cbc..04b472d 100644 --- src/tmpfiles/tmpfiles.c +++ src/tmpfiles/tmpfiles.c @@ -217,19 +217,16 @@ static bool unix_socket_alive(const char *fn) { } static int dir_is_mount_point(DIR *d, const char *subdir) { - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ }; int mount_id_parent, mount_id; int r_p, r; - h = alloca(MAX_HANDLE_SZ); - - h->handle_bytes = MAX_HANDLE_SZ; - r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0); + r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0); if (r_p < 0) r_p = -errno; - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0); + h.handle.handle_bytes = MAX_HANDLE_SZ; + r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0); if (r < 0) r = -errno; -- 1.7.9.2