summaryrefslogtreecommitdiffstats
path: root/libmount/src
diff options
context:
space:
mode:
authorKarel Zak2017-11-08 16:47:40 +0100
committerKarel Zak2017-11-08 17:03:59 +0100
commit06ff935ec3ad2290025b555ff32b590680af565f (patch)
treee9650c7c99554bae3fa903e865048f99509fd806 /libmount/src
parentlibmount: Allow MNT_FORCE and MNT_DETACH at umount (diff)
downloadkernel-qcow2-util-linux-06ff935ec3ad2290025b555ff32b590680af565f.tar.gz
kernel-qcow2-util-linux-06ff935ec3ad2290025b555ff32b590680af565f.tar.xz
kernel-qcow2-util-linux-06ff935ec3ad2290025b555ff32b590680af565f.zip
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) Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src')
-rw-r--r--libmount/src/mountP.h2
-rw-r--r--libmount/src/tab_parse.c7
-rw-r--r--libmount/src/tab_update.c11
-rw-r--r--libmount/src/utils.c42
4 files changed, 42 insertions, 20 deletions
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index e01de337d..b00426d67 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -242,7 +242,7 @@ struct libmnt_table {
void *userdata;
};
-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 b17a22913..02dd0c961 100644
--- a/libmount/src/tab_parse.c
+++ b/libmount/src/tab_parse.c
@@ -838,7 +838,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;
@@ -846,7 +846,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) {
DBG(TAB, ul_debugobj(tb, "new tab for file: %s", filename));
@@ -875,7 +876,7 @@ struct libmnt_table *mnt_new_table_from_file(const char *filename)
if (!filename)
return NULL;
- return __mnt_new_table_from_file(filename, MNT_FMT_GUESS);
+ 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 e95713301..23a5a8bc5 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -571,6 +571,7 @@ leave:
unlink(uq); /* be paranoid */
free(uq);
+ DBG(UPDATE, ul_debugobj(upd, "%s: done [rc=%d]", upd->filename, rc));
return rc;
}
@@ -699,7 +700,7 @@ static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc)
return -MNT_ERR_LOCK;
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)
@@ -725,7 +726,7 @@ static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc
return -MNT_ERR_LOCK;
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) {
@@ -754,7 +755,7 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l
return -MNT_ERR_LOCK;
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);
@@ -791,7 +792,7 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *
return -MNT_ERR_LOCK;
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),
@@ -894,7 +895,7 @@ int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
}
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 (lc)
mnt_unlock_file(lc);
if (!tb)
diff --git a/libmount/src/utils.c b/libmount/src/utils.c
index 711d1683e..5db5494d3 100644
--- a/libmount/src/utils.c
+++ b/libmount/src/utils.c
@@ -645,18 +645,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, ul_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, ul_debug(" access OK"));
+ return 0;
+ } else if (errno != ENOENT) {
+ DBG(UTILS, ul_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, ul_debug(" access %s [%s]", rc ? "FAILED" : "OK", directory));
+ return rc;
+ } else
+#endif
{
+ DBG(UTILS, ul_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)
@@ -664,7 +683,6 @@ static int try_write(const char *filename)
else
close(fd);
}
-#endif
return rc;
}
@@ -698,7 +716,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable)
/* file exists */
if (S_ISREG(st.st_mode)) {
if (writable)
- *writable = !try_write(filename);
+ *writable = !try_write(filename, NULL);
DBG(UTILS, ul_debug("%s: writable", filename));
return 1;
}
@@ -707,7 +725,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) {
DBG(UTILS, ul_debug("%s: writable", filename));
return 1;
@@ -747,7 +765,7 @@ int mnt_has_regular_utab(const char **utab, int *writable)
/* file exists */
if (S_ISREG(st.st_mode)) {
if (writable)
- *writable = !try_write(filename);
+ *writable = !try_write(filename, NULL);
return 1;
}
goto done; /* it's not a regular file */
@@ -764,11 +782,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;
}