Skip to content

Commit

Permalink
libmount: update utab after successful extern helper mount
Browse files Browse the repository at this point in the history
This patch allows to maintain private utab libmount file also for
external mount/umount helpers that are not linked with libmount.

The libmount check if utab has been updated after successful extern
helper execution (status=0). If not then the file is updated.

This patch affects only 'user' fstab mount option. So, for example
with suid mount.cifs you can use:

 //server/foo    /mnt  cifs   username=foo,noauto,user

Signed-off-by: Karel Zak <kzak@redhat.com>
  • Loading branch information
karelzak committed Nov 4, 2013
1 parent 889fc9f commit 7e0c061
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 10 deletions.
30 changes: 20 additions & 10 deletions libmount/src/context.c
Expand Up @@ -1725,10 +1725,6 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
DBG(CXT, mnt_debug_h(cxt, "skip update: NOMTAB flag"));
return 0;
}
if (cxt->helper) {
DBG(CXT, mnt_debug_h(cxt, "skip update: external helper"));
return 0;
}
if (!cxt->mtab_writable && !cxt->utab_writable) {
DBG(CXT, mnt_debug_h(cxt, "skip update: no writable destination"));
return 0;
Expand Down Expand Up @@ -1777,16 +1773,30 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
DBG(CXT, mnt_debug_h(cxt, "don't update: NOMTAB flag"));
return 0;
}
if (cxt->helper) {
DBG(CXT, mnt_debug_h(cxt, "don't update: external helper"));
return 0;
}
if (!cxt->update || !mnt_update_is_ready(cxt->update)) {
DBG(CXT, mnt_debug_h(cxt, "don't update: no update prepared"));
return 0;
}
if (cxt->syscall_status) {
DBG(CXT, mnt_debug_h(cxt, "don't update: syscall failed/not called"));

/* check utab update when external helper executed */
if (mnt_context_helper_executed(cxt)
&& mnt_context_get_helper_status(cxt) == 0
&& cxt->utab_writable) {

if (mnt_update_already_done(cxt->update, cxt->lock)) {
DBG(CXT, mnt_debug_h(cxt, "don't update: error evaluate or already updated"));
return 0;
}
} else if (cxt->helper) {
DBG(CXT, mnt_debug_h(cxt, "don't update: external helper"));
return 0;
}

if (cxt->syscall_status != 0
&& !(mnt_context_helper_executed(cxt) &&
mnt_context_get_helper_status(cxt) == 0)) {

DBG(CXT, mnt_debug_h(cxt, "don't update: syscall/helper failed/not called"));
return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions libmount/src/mountP.h
Expand Up @@ -460,5 +460,7 @@ extern int mnt_context_set_tabfilter(struct libmnt_context *cxt,
/* tab_update.c */
extern int mnt_update_set_filename(struct libmnt_update *upd,
const char *filename, int userspace_only);
extern int mnt_update_already_done(struct libmnt_update *upd,
struct libmnt_lock *lc);

#endif /* _LIBMOUNT_PRIVATE_H */
62 changes: 62 additions & 0 deletions libmount/src/tab_update.c
Expand Up @@ -286,6 +286,7 @@ int mnt_update_force_rdonly(struct libmnt_update *upd, int rdonly)
return rc;
}


/*
* Allocates an utab entry (upd->fs) for mount/remount. This function should be
* called *before* mount(2) syscall. The @fs is used as a read-only template.
Expand Down Expand Up @@ -873,6 +874,67 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
return rc;
}

int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
{
struct libmnt_table *tb = NULL;
struct libmnt_lock *lc0 = lc;
int rc = 0;

if (!upd || !upd->filename || (!upd->fs && !upd->target))
return -EINVAL;

DBG(UPDATE, mnt_debug_h(upd, "%s: checking for previous update", upd->filename));

if (!lc) {
lc = mnt_new_lock(upd->filename, 0);
if (lc)
mnt_lock_block_signals(lc, TRUE);
}
if (lc && upd->userspace_only)
mnt_lock_use_simplelock(lc, TRUE); /* use flock */
if (lc)
rc = mnt_lock_file(lc);
if (rc)
goto done;

tb = __mnt_new_table_from_file(upd->filename,
upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB);
if (lc)
mnt_unlock_file(lc);
if (!tb)
goto done;

if (upd->fs) {
/* mount */
const char *tgt = mnt_fs_get_target(upd->fs);
const char *src = mnt_fs_get_bindsrc(upd->fs) ?
mnt_fs_get_bindsrc(upd->fs) :
mnt_fs_get_source(upd->fs);

if (mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD)) {
DBG(UPDATE, mnt_debug_h(upd, "%s: found %s %s",
upd->filename, src, tgt));
rc = 1;
}
} else if (upd->target) {
/* umount */
if (!mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD)) {
DBG(UPDATE, mnt_debug_h(upd, "%s: not-found (umounted) %s",
upd->filename, upd->target));
rc = 1;
}
}

mnt_unref_table(tb);
done:
if (lc && lc != lc0)
mnt_free_lock(lc);
DBG(UPDATE, mnt_debug_h(upd, "%s: previous update check done [rc=%d]",
upd->filename, rc));
return rc;
}


#ifdef TEST_PROGRAM

static int update(const char *target, struct libmnt_fs *fs, unsigned long mountflags)
Expand Down

0 comments on commit 7e0c061

Please sign in to comment.