diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-10-28 19:06:50 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-10-28 19:06:50 +0000 |
commit | c0d43a22da78c42c835d4a2242c0ddfe206c625b (patch) | |
tree | 1f577b35a7c38fc7620d248c2c71b8b91ad47bf9 /usr/src | |
parent | 981fa45c14e1fbc88bdb8e00929b095f7b80caa9 (diff) | |
download | illumos-joyent-c0d43a22da78c42c835d4a2242c0ddfe206c625b.tar.gz |
OS-4710 mount tmpfs fails when specifying 'uid=%s,gid=%s' on lx branded zone (centos6)
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/mount.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/mount.c b/usr/src/lib/brand/lx/lx_brand/common/mount.c index 2c3d1ae9b5..82d316950d 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/mount.c +++ b/usr/src/lib/brand/lx/lx_brand/common/mount.c @@ -88,6 +88,8 @@ mount_opt_t lx_sysfs_options[] = { mount_opt_t lx_tmpfs_options[] = { { "size", MOUNT_OPT_BYTESIZE }, { "mode", MOUNT_OPT_UINT }, + { "uid", MOUNT_OPT_UINT }, + { "gid", MOUNT_OPT_UINT }, { NULL, MOUNT_OPT_INVALID } }; @@ -299,6 +301,73 @@ i_lx_opt_verify(char *opts, mount_opt_t *mop) return (0); } +/* + * Remove an option from the string and save it in the provided buffer. + * The option string should have already been verified as valid. + * Return 0 if not present, -1 if error, and 1 if present and fine. + */ +static int +opt_rm(char *opts, char *rmopt, char *retstr, int retlen) +{ + int opts_len = strlen(opts); + char *optstart, *optend; + int optlen; + + assert((opts != NULL) && (rmopt != NULL)); + + retstr[0] = '\0'; + + /* If no options were specified, there's no problem. */ + if (opts_len == 0) + return (0); + + if ((optstart = strstr(opts, rmopt)) == NULL) + return (0); + + for (optend = optstart; *optend != ',' && *optend != '\0'; optend++) + ; + + optlen = optend - optstart; + if (optlen >= retlen) + return (-1); + strncpy(retstr, optstart, optlen); + retstr[optlen] = '\0'; + + if (*optend == ',') + optend++; + + optlen = strlen(optend) + 1; + bcopy(optend, optstart, optlen); + + if (*optstart == '\0' && optstart != opts) { + /* removed last opt and it had a preceeding opt, remove comma */ + *(optstart - 1) = '\0'; + } + + return (1); +} + +static int +opt_id_val(char *opt, int *valp) +{ + char *vp; + long lval; + + if ((vp = strchr(opt, '=')) == NULL) + return (-1); + + vp++; + if (!isdigit(*vp)) + return (-1); + + lval = strtol(vp, &vp, 10); + if (*vp != '\0' || lval > INT_MAX) + return (-1); + + *valp = (int)lval; + return (0); +} + static int i_add_option(char *option, char *buf, size_t buf_size) { @@ -644,8 +713,13 @@ lx_mount(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, char fstype[MAXPATHLEN], options[MAX_MNTOPT_STR]; int sflags, rv; long res; + boolean_t is_tmpfs = B_FALSE; boolean_t is_cgrp = B_FALSE; + /* Variable for tmpfs mounts. */ + int uid = -1; + int gid = -1; + /* Variables needed for nfs mounts. */ lx_nfs_mount_data_t lx_nmd; struct nfs_args nfs_args; @@ -706,6 +780,8 @@ lx_mount(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, return (-errno); } } else if (strcmp(fstype, "tmpfs") == 0) { + char idstr[64]; + int idval; /* Copy in Linux mount options. */ if (datap != NULL) { @@ -732,6 +808,29 @@ lx_mount(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, (void) strlcat(options, "mode=1777", sizeof (options)); } + switch (opt_rm(options, "uid=", idstr, sizeof (idstr))) { + case 0: + uid = -1; + break; + case 1: + if (opt_id_val(idstr, &uid) < 0) + return (-EINVAL); + break; + default: + return (-E2BIG); + } + switch (opt_rm(options, "gid=", idstr, sizeof (idstr))) { + case 0: + gid = -1; + break; + case 1: + if (opt_id_val(idstr, &gid) < 0) + return (-EINVAL); + break; + default: + return (-E2BIG); + } + /* * Linux seems to always allow overlay mounts. We allow this * everywhere except under /dev where it interferes with device @@ -741,6 +840,8 @@ lx_mount(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, strncmp(targetp, "/dev/", 5) != 0) sflags |= MS_OVERLAY; + is_tmpfs = B_TRUE; + } else if (strcmp(fstype, "proc") == 0) { struct stat64 sb; @@ -955,6 +1056,12 @@ lx_mount(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, */ (void) umount(target); return (-ENOMEM); + } else if (is_tmpfs) { + /* Handle uid/gid mount options. */ + if (uid != -1 || gid != -1) + (void) chown(target, uid, gid); + return (0); + } else { return (0); } |