You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
7.1 KiB
226 lines
7.1 KiB
From 5d238002ff22241a7d04608102a2182aa74d2b69 Mon Sep 17 00:00:00 2001 |
|
From: Karel Zak <kzak@redhat.com> |
|
Date: Wed, 8 Nov 2017 16:47:40 +0100 |
|
Subject: [PATCH] libmount: fix access() utab write test |
|
|
|
The commit c08396c7691e1e6a04b6b45892e7e4612ceed8d7 replaces |
|
open(O_CREATE) with ecaccess(). Unfortunately, another code depends on |
|
the original behavior. |
|
|
|
* let's make utab when really necessary rather than in the try_write() test |
|
|
|
* __mnt_new_table_from_file() returns NULL if tab-file does not |
|
exists. This is incorrect for tab_update.c stuff. We need empty table |
|
in this case. |
|
|
|
* we can check /run/mount/ directory for write access if |
|
eaccess(filename) return ENOENT (because file does not exist) |
|
|
|
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1499760 |
|
Upstream: http://github.com/karelzak/util-linux/commit/06ff935ec3ad2290025b555ff32b590680af565f |
|
Signed-off-by: Karel Zak <kzak@redhat.com> |
|
--- |
|
libmount/src/mountP.h | 2 +- |
|
libmount/src/tab_parse.c | 11 +++++++---- |
|
libmount/src/tab_update.c | 9 +++++---- |
|
libmount/src/utils.c | 42 +++++++++++++++++++++++++++++++----------- |
|
4 files changed, 44 insertions(+), 20 deletions(-) |
|
|
|
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h |
|
index 6cabcedeb..8b3f92e17 100644 |
|
--- a/libmount/src/mountP.h |
|
+++ b/libmount/src/mountP.h |
|
@@ -278,7 +278,7 @@ struct libmnt_table { |
|
struct list_head ents; /* list of entries (libmnt_fs) */ |
|
}; |
|
|
|
-extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt); |
|
+extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent); |
|
|
|
/* |
|
* Tab file format |
|
diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c |
|
index 987e671fa..c629c67ad 100644 |
|
--- a/libmount/src/tab_parse.c |
|
+++ b/libmount/src/tab_parse.c |
|
@@ -714,7 +714,7 @@ int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) |
|
return __mnt_table_parse_dir(tb, dirname); |
|
} |
|
|
|
-struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) |
|
+struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent) |
|
{ |
|
struct libmnt_table *tb; |
|
struct stat st; |
|
@@ -723,7 +723,8 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) |
|
if (!filename) |
|
return NULL; |
|
if (stat(filename, &st)) |
|
- return NULL; |
|
+ return empty_for_enoent ? mnt_new_table() : NULL; |
|
+ |
|
tb = mnt_new_table(); |
|
if (tb) { |
|
tb->fmt = fmt; |
|
@@ -748,8 +749,10 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) |
|
*/ |
|
struct libmnt_table *mnt_new_table_from_file(const char *filename) |
|
{ |
|
- assert(filename); |
|
- return __mnt_new_table_from_file(filename, MNT_FMT_GUESS); |
|
+ if (!filename) |
|
+ return NULL; |
|
+ |
|
+ return __mnt_new_table_from_file(filename, MNT_FMT_GUESS, 0); |
|
} |
|
|
|
/** |
|
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c |
|
index 1e7f32be0..5f503cad7 100644 |
|
--- a/libmount/src/tab_update.c |
|
+++ b/libmount/src/tab_update.c |
|
@@ -567,6 +567,7 @@ leave: |
|
|
|
unlink(uq); /* be paranoid */ |
|
free(uq); |
|
+ DBG(UPDATE, mnt_debug_h(upd, "%s: done [rc=%d]", upd->filename, rc)); |
|
return rc; |
|
} |
|
|
|
@@ -600,7 +601,7 @@ static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc) |
|
return rc; |
|
|
|
tb = __mnt_new_table_from_file(upd->filename, |
|
- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
|
+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); |
|
if (tb) |
|
rc = add_file_entry(tb, upd); |
|
if (lc) |
|
@@ -626,7 +627,7 @@ static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc |
|
return rc; |
|
|
|
tb = __mnt_new_table_from_file(upd->filename, |
|
- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
|
+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); |
|
if (tb) { |
|
struct libmnt_fs *rem = mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD); |
|
if (rem) { |
|
@@ -656,7 +657,7 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l |
|
return rc; |
|
|
|
tb = __mnt_new_table_from_file(upd->filename, |
|
- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
|
+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); |
|
if (tb) { |
|
struct libmnt_fs *cur = mnt_table_find_target(tb, |
|
mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); |
|
@@ -693,7 +694,7 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock * |
|
return rc; |
|
|
|
tb = __mnt_new_table_from_file(upd->filename, |
|
- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
|
+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); |
|
if (tb) { |
|
struct libmnt_fs *cur = mnt_table_find_target(tb, |
|
mnt_fs_get_target(fs), |
|
diff --git a/libmount/src/utils.c b/libmount/src/utils.c |
|
index a275d0a0e..fa33bd9a1 100644 |
|
--- a/libmount/src/utils.c |
|
+++ b/libmount/src/utils.c |
|
@@ -651,18 +651,37 @@ done: |
|
return rc; |
|
} |
|
|
|
-static int try_write(const char *filename) |
|
+static int try_write(const char *filename, const char *directory) |
|
{ |
|
int rc = 0; |
|
|
|
if (!filename) |
|
return -EINVAL; |
|
|
|
+ DBG(UTILS, mnt_debug("try write %s dir: %s", filename, directory)); |
|
+ |
|
#ifdef HAVE_EACCESS |
|
- if (eaccess(filename, R_OK|W_OK) != 0) |
|
- rc = -errno; |
|
-#else |
|
+ /* Try eaccess() first, because open() is overkill, may be monitored by |
|
+ * audit and we don't want to fill logs by our checks... |
|
+ */ |
|
+ if (eaccess(filename, R_OK|W_OK) == 0) { |
|
+ DBG(UTILS, mnt_debug(" access OK")); |
|
+ return 0; |
|
+ } else if (errno != ENOENT) { |
|
+ DBG(UTILS, mnt_debug(" access FAILED")); |
|
+ return -errno; |
|
+ } else if (directory) { |
|
+ /* file does not exist; try if directory is writable */ |
|
+ if (eaccess(directory, R_OK|W_OK) != 0) |
|
+ rc = -errno; |
|
+ |
|
+ DBG(UTILS, mnt_debug(" access %s [%s]", rc ? "FAILED" : "OK", directory)); |
|
+ return rc; |
|
+ } else |
|
+#endif |
|
{ |
|
+ DBG(UTILS, mnt_debug(" doing open-write test")); |
|
+ |
|
int fd = open(filename, O_RDWR|O_CREAT|O_CLOEXEC, |
|
S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); |
|
if (fd < 0) |
|
@@ -670,7 +689,6 @@ static int try_write(const char *filename) |
|
else |
|
close(fd); |
|
} |
|
-#endif |
|
return rc; |
|
} |
|
|
|
@@ -704,7 +722,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) |
|
/* file exist */ |
|
if (S_ISREG(st.st_mode)) { |
|
if (writable) |
|
- *writable = !try_write(filename); |
|
+ *writable = !try_write(filename, NULL); |
|
return 1; |
|
} |
|
goto done; |
|
@@ -712,7 +730,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) |
|
|
|
/* try to create the file */ |
|
if (writable) { |
|
- *writable = !try_write(filename); |
|
+ *writable = !try_write(filename, NULL); |
|
if (*writable) |
|
return 1; |
|
} |
|
@@ -750,7 +768,7 @@ int mnt_has_regular_utab(const char **utab, int *writable) |
|
/* file exist */ |
|
if (S_ISREG(st.st_mode)) { |
|
if (writable) |
|
- *writable = !try_write(filename); |
|
+ *writable = !try_write(filename, NULL); |
|
return 1; |
|
} |
|
goto done; /* it's not regular file */ |
|
@@ -767,11 +785,13 @@ int mnt_has_regular_utab(const char **utab, int *writable) |
|
rc = mkdir(dirname, S_IWUSR| |
|
S_IRUSR|S_IRGRP|S_IROTH| |
|
S_IXUSR|S_IXGRP|S_IXOTH); |
|
- free(dirname); |
|
- if (rc && errno != EEXIST) |
|
+ if (rc && errno != EEXIST) { |
|
+ free(dirname); |
|
goto done; /* probably EACCES */ |
|
+ } |
|
|
|
- *writable = !try_write(filename); |
|
+ *writable = !try_write(filename, dirname); |
|
+ free(dirname); |
|
if (*writable) |
|
return 1; |
|
} |
|
-- |
|
2.13.6 |
|
|
|
|