Beispiel #1
0
/* returns: error = -1, success = 0 , unknown = 1 */
static int is_vers4(struct libmnt_context *cxt)
{
    struct libmnt_fs *fs = mnt_context_get_fs(cxt);
    struct libmnt_table *tb = NULL;
    const char *src = mnt_context_get_source(cxt),
                *tgt = mnt_context_get_target(cxt);
    int rc = 1;

    if (!src || !tgt)
        return -1;

    if (!mnt_fs_is_kernel(fs)) {
        struct libmnt_table *tb = mnt_new_table_from_file("/proc/mounts");

        if (!tb)
            return -1;
        fs = mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD);
    }

    if (fs) {
        const char *type = mnt_fs_get_fstype(fs);
        if (type && strcmp(type, "nfs4") == 0)
            rc = 0;
    }
    mnt_free_table(tb);
    return rc;
}
Beispiel #2
0
/**
 * mnt_context_prepare_umount:
 * @cxt: mount context
 *
 * Prepare context for umounting, unnecessary for mnt_context_umount().
 *
 * Returns: 0 on success, and negative number in case of error.
 */
int mnt_context_prepare_umount(struct libmnt_context *cxt)
{
	int rc;

	assert(cxt);
	assert(cxt->fs);
	assert(cxt->helper_exec_status == 1);
	assert(cxt->syscall_status == 1);

	if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs))
		return -EINVAL;
	if (!mnt_context_get_source(cxt) && !mnt_context_get_target(cxt))
		return -EINVAL;
	if (cxt->flags & MNT_FL_PREPARED)
		return 0;

	free(cxt->helper);	/* be paranoid */
	cxt->helper = NULL;
	cxt->action = MNT_ACT_UMOUNT;

	rc = lookup_umount_fs(cxt);
	if (!rc)
		rc = mnt_context_merge_mflags(cxt);
	if (!rc)
		rc = evaluate_permissions(cxt);

	if (!rc && !cxt->helper) {

		if (cxt->user_mountflags & MNT_MS_HELPER)
			/* on helper= mount option based helper */
			rc = prepare_helper_from_options(cxt, "helper");

		if (!rc && !cxt->helper)
			/* on fstype based helper */
			rc = mnt_context_prepare_helper(cxt, "umount", NULL);
	}

	if (!rc && (cxt->user_mountflags & MNT_MS_LOOP))
		/* loop option explicitly specified in mtab, detach this loop */
		mnt_context_enable_loopdel(cxt, TRUE);

	if (!rc && mnt_context_is_loopdel(cxt) && cxt->fs) {
		const char *src = mnt_fs_get_srcpath(cxt->fs);

		if (src && (!is_loopdev(src) || loopdev_is_autoclear(src)))
			mnt_context_enable_loopdel(cxt, FALSE);
	}

	if (rc) {
		DBG(CXT, mnt_debug_h(cxt, "umount: preparing failed"));
		return rc;
	}
	cxt->flags |= MNT_FL_PREPARED;
	return rc;
}
Beispiel #3
0
/*
 * this has to be called before fix_optstr()
 */
static int evaluate_permissions(struct libmnt_context *cxt)
{
	unsigned long u_flags = 0;

	assert(cxt);
	assert(cxt->fs);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	if (!cxt)
		return -EINVAL;
	if (!cxt->fs)
		return 0;

	DBG(CXT, mnt_debug_h(cxt, "mount: evaluating permissions"));

	mnt_context_get_user_mflags(cxt, &u_flags);

	if (!mnt_context_is_restricted(cxt)) {
		/*
		 * superuser mount
		 */
		cxt->user_mountflags &= ~MNT_MS_OWNER;
		cxt->user_mountflags &= ~MNT_MS_GROUP;
		cxt->user_mountflags &= ~MNT_MS_USER;
		cxt->user_mountflags &= ~MNT_MS_USERS;
	} else {
		/*
		 * user mount
		 */
		if (!(cxt->flags & MNT_FL_TAB_APPLIED))
		{
			DBG(CXT, mnt_debug_h(cxt, "perms: fstab not applied, ignore user mount"));
			return -EPERM;
		}

		/*
		 * Note that MS_OWNERSECURE and MS_SECURE mount options
		 * are applied by mnt_optstr_get_flags() from mnt_context_merge_mflags()
		 */


		/*
		 * MS_OWNER: Allow owners to mount when fstab contains the
		 * owner option.  Note that this should never be used in a high
		 * security environment, but may be useful to give people at
		 * the console the possibility of mounting a floppy.  MS_GROUP:
		 * Allow members of device group to mount. (Martin Dickopp)
		 */
		if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) {
			struct stat sb;
			struct libmnt_cache *cache = NULL;
			char *xsrc = NULL;
			const char *srcpath = mnt_fs_get_srcpath(cxt->fs);

			if (!srcpath) {					/* Ah... source is TAG */
				cache = mnt_context_get_cache(cxt);
				xsrc = mnt_resolve_spec(
						mnt_context_get_source(cxt),
						cache);
				srcpath = xsrc;
			}
			if (!srcpath) {
				DBG(CXT, mnt_debug_h(cxt, "perms: src undefined"));
				return -EPERM;
			}

			if (strncmp(srcpath, "/dev/", 5) == 0 &&
			    stat(srcpath, &sb) == 0 &&
			    (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) ||
			     ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid))))

				cxt->user_mountflags |= MNT_MS_USER;

			if (!cache)
				free(xsrc);
		}

		if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) {
			DBG(CXT, mnt_debug_h(cxt, "permissions evaluation ends with -EPERMS"));
			return -EPERM;
		}
	}

	return 0;
}
Beispiel #4
0
static int mount_main(struct libmnt_context *cxt, int argc, char **argv)
{
    int rc, c;
    struct libmnt_fs *fs;
    char *spec = NULL, *mount_point = NULL, *opts = NULL;

    static const struct option longopts[] = {
        { "fake", 0, 0, 'f' },
        { "help", 0, 0, 'h' },
        { "no-mtab", 0, 0, 'n' },
        { "read-only", 0, 0, 'r' },
        { "ro", 0, 0, 'r' },
        { "verbose", 0, 0, 'v' },
        { "version", 0, 0, 'V' },
        { "read-write", 0, 0, 'w' },
        { "rw", 0, 0, 'w' },
        { "options", 1, 0, 'o' },
        { "sloppy", 0, 0, 's' },
        { NULL, 0, 0, 0 }
    };

    mount_config_init(progname);
    mnt_context_init_helper(cxt, MNT_ACT_MOUNT, 0);

    while ((c = getopt_long(argc, argv, "fhnrVvwo:s", longopts, NULL)) != -1) {

        rc = mnt_context_helper_setopt(cxt, c, optarg);
        if (rc == 0)		/* valid option */
            continue;
        if (rc < 0)		/* error (probably ENOMEM) */
            goto err;
        /* rc==1 means unknow option */
        switch (c) {
        case 'V':
            printf("%s: ("PACKAGE_STRING")\n", progname);
            return EX_SUCCESS;
        case 'h':
        default:
            mount_usage();
            return EX_USAGE;
        }
    }

    if (optind < argc)
        spec = argv[optind++];
    if (optind < argc)
        mount_point = argv[optind++];

    if (!mount_point) {
        nfs_error(_("%s: no mount point provided"), progname);
        goto err;
    }
    if (!spec) {
        nfs_error(_("%s: no mount spec provided"), progname);
        goto err;
    }

    if (geteuid() != 0) {
        nfs_error(_("%s: not installed setuid - "
                    "\"user\" NFS mounts not supported."), progname);
        goto err;
    }

    verbose = mnt_context_is_verbose(cxt);
    sloppy = mnt_context_is_sloppy(cxt);
    nomtab = mnt_context_is_nomtab(cxt);

    if (strcmp(progname, "mount.nfs4") == 0)
        mnt_context_set_fstype(cxt, "nfs4");
    else
        mnt_context_set_fstype(cxt, "nfs");	/* default */

    rc = mnt_context_set_source(cxt, spec);
    if (!rc)
        mnt_context_set_target(cxt, mount_point);
    if (rc) {
        nfs_error(_("%s: failed to set spec or mountpoint: %s"),
                  progname, strerror(errno));
        goto err;
    }

    mount_point = mnt_resolve_path(mount_point,
                                   mnt_context_get_cache(cxt));

    if (chk_mountpoint(mount_point))
        goto err;
    /*
     * Concatenate mount options from the configuration file
     */
    fs = mnt_context_get_fs(cxt);
    if (fs) {
        opts = mnt_fs_strdup_options(fs);

        opts = mount_config_opts(spec, mount_point, opts);
        mnt_fs_set_options(fs, opts);
    }

    rc = mnt_context_prepare_mount(cxt);
    if (rc) {
        nfs_error(_("%s: failed to prepare mount: %s\n"),
                  progname, strerror(-rc));
        goto err;
    }

    rc = try_mount(cxt, FOREGROUND);

    if (rc == EX_BG) {
        printf(_("%s: backgrounding \"%s\"\n"),
               progname, mnt_context_get_source(cxt));
        printf(_("%s: mount options: \"%s\"\n"),
               progname, opts);

        fflush(stdout);

        if (daemon(0, 0)) {
            nfs_error(_("%s: failed to start "
                        "background process: %s\n"),
                      progname, strerror(errno));
            exit(EX_FAIL);
        }

        rc = try_mount(cxt, BACKGROUND);

        if (verbose && rc)
            printf(_("%s: giving up \"%s\"\n"),
                   progname, mnt_context_get_source(cxt));
    }

    mnt_context_set_syscall_status(cxt, rc == EX_SUCCESS ? 0 : -1);
    mnt_context_finalize_mount(cxt);	/* mtab update */
    return rc;
err:
    return EX_FAIL;
}
Beispiel #5
0
static int umount_main(struct libmnt_context *cxt, int argc, char **argv)
{
    int rc, c;
    char *spec = NULL, *opts = NULL;

    static const struct option longopts[] = {
        { "force", 0, 0, 'f' },
        { "help", 0, 0, 'h' },
        { "no-mtab", 0, 0, 'n' },
        { "verbose", 0, 0, 'v' },
        { "read-only", 0, 0, 'r' },
        { "lazy", 0, 0, 'l' },
        { "types", 1, 0, 't' },
        { NULL, 0, 0, 0 }
    };

    mnt_context_init_helper(cxt, MNT_ACT_UMOUNT, 0);

    while ((c = getopt_long (argc, argv, "fvnrlh", longopts, NULL)) != -1) {

        rc = mnt_context_helper_setopt(cxt, c, optarg);
        if (rc == 0)		/* valid option */
            continue;
        if (rc < 0)		/* error (probably ENOMEM) */
            goto err;
        /* rc==1 means unknow option */
        umount_usage();
        return EX_USAGE;
    }

    if (optind < argc)
        spec = argv[optind++];

    if (!spec || (*spec != '/' && strchr(spec,':') == NULL)) {
        nfs_error(_("%s: no mount point provided"), progname);
        return EX_USAGE;
    }

    if (mnt_context_set_target(cxt, spec))
        goto err;
    if (mnt_context_set_fstype_pattern(cxt, "nfs,nfs4"))	/* restrict filesystems */
        goto err;

    /* read mtab/fstab, evaluate permissions, etc. */
    rc = mnt_context_prepare_umount(cxt);
    if (rc) {
        nfs_error(_("%s: failed to prepare umount: %s\n"),
                  progname, strerror(-rc));
        goto err;
    }

    opts = retrieve_mount_options(mnt_context_get_fs(cxt));

    if (!mnt_context_is_lazy(cxt)) {
        if (opts) {
            /* we have full FS description (e.g. from mtab or /proc) */
            switch (is_vers4(cxt)) {
            case 0:
                /* We ignore the error from nfs_umount23.
                 * If the actual umount succeeds (in del_mtab),
                 * we don't want to signal an error, as that
                 * could cause /sbin/mount to retry!
                 */
                nfs_umount23(mnt_context_get_source(cxt), opts);
                break;
            case 1:			/* unknown */
                break;
            default:		/* error */
                goto err;
            }
        } else
            /* strange, no entry in mtab or /proc not mounted */
            nfs_umount23(spec, "tcp,v3");
    }

    rc = mnt_context_do_umount(cxt);	/* call umount(2) syscall */
    mnt_context_finalize_mount(cxt);	/* mtab update */

    if (rc && !mnt_context_get_status(cxt)) {
        /* mnt_context_do_umount() returns errno if umount(2) failed */
        umount_error(rc, spec);
        goto err;
    }

    free(opts);
    return EX_SUCCESS;
err:
    free(opts);
    return EX_FAIL;
}