diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-06-14 11:46:02 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-06-14 11:46:02 +0000 |
| commit | cc3d7c4906f9242753f7514c92245cbe1612ea02 (patch) | |
| tree | 182d5564411e3e3d3bfaf43a1c878eb835428d6d | |
| parent | 4152d8858319048f89c6066931dfabeb820333e9 (diff) | |
| parent | 2889ec41c05e9ffe1890b529b3111354da325aeb (diff) | |
| download | illumos-joyent-cc3d7c4906f9242753f7514c92245cbe1612ea02.tar.gz | |
[illumos-gate merge]
commit 2889ec41c05e9ffe1890b529b3111354da325aeb
8311 ZFS_READONLY is a little too strict
commit 796b8631498f69a3e21b5c35aee280499f64420e
8332 krb5: misleading-indentation
commit c1eb8ad45781fe675aa558a47a11345293533238
8204 Makefile changes in zfstest cannot cope with empty directories
commit d5767f310a0330fcb172a1651b2c9301e53b9aef
8334 ipf: self-comparison always evaluates to false
commit 843c2111b160463f014d325560ad4b051711928e
8375 Kernel memory leak in nvpair code
commit 403a8da73c64ff9dfb6230ba045c765a242213fb
5220 L2ARC does not support devices that do not provide 512B access
commit 4ec4134be29a3b00791f6d70074168a6a3ff4fb3
8317 ddi_periodic_add(9F) has wrong type for arg in summary
commit 56849bc6aade3a04eb051dc383a2091c220385c4
8322 nl: misleading-indentation
commit 6dd72a43d2e43185833c20e7f0c4cb88a4d37ec8
8106 authloopback_marshal() can violate the RPC specification
8109 Kernel AUTH_SYS and AUTH_LOOPBACK implementation can ignore provided credentials
commit 1d8d40bd3f903c0d0fa71c26b4548d2d47260251
8354 sync regcomp(3C) with upstream (fix make catalog)
26 files changed, 655 insertions, 216 deletions
diff --git a/usr/src/cmd/ipf/tools/ipfcomp.c b/usr/src/cmd/ipf/tools/ipfcomp.c index b99a6f8385..15405c1cd3 100644 --- a/usr/src/cmd/ipf/tools/ipfcomp.c +++ b/usr/src/cmd/ipf/tools/ipfcomp.c @@ -7,13 +7,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#if !defined(lint) -static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfcomp.c,v 1.24.2.2 2004/04/28 10:34:44 darrenr Exp $"; -#endif - #include "ipf.h" @@ -391,7 +384,7 @@ extern frentry_t *ipfrule_match_out_%s __P((fr_info_t *, u_32_t *));\n\ extern frentry_t *ipf_rules_out_%s[%d];\n", grp->fg_name, grp->fg_name, outcount); - for (g = groups; g != g; g = g->fg_next) + for (g = groups; g != grp; g = g->fg_next) if ((strncmp(g->fg_name, grp->fg_name, FR_GROUPLEN) == 0) && g->fg_flags == grp->fg_flags) diff --git a/usr/src/cmd/krb5/kadmin/dbutil/dump.c b/usr/src/cmd/krb5/kadmin/dbutil/dump.c index a512d7527f..3f6b3b8f54 100644 --- a/usr/src/cmd/krb5/kadmin/dbutil/dump.c +++ b/usr/src/cmd/krb5/kadmin/dbutil/dump.c @@ -2833,9 +2833,9 @@ load_db(argc, argv) exit_status++; goto error; } - } - else + } else { db_locked = 1; + } if (log_ctx && log_ctx->iproprole) { if (add_update) diff --git a/usr/src/cmd/krb5/kadmin/server/server_stubs.c b/usr/src/cmd/krb5/kadmin/server/server_stubs.c index 76eef7227a..b90f5d54d1 100644 --- a/usr/src/cmd/krb5/kadmin/server/server_stubs.c +++ b/usr/src/cmd/krb5/kadmin/server/server_stubs.c @@ -554,42 +554,42 @@ create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp) log_unauth("kadm5_create_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { - ret.code = kadm5_create_principal((void *)handle, + ret.code = kadm5_create_principal((void *)handle, &arg->rec, arg->mask, arg->passwd); /* Solaris Kerberos */ - if( ret.code != 0 ) + if( ret.code != 0 ) errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code); - audit_kadmind_auth(rqstp->rq_xprt, l_port, + audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_create_principal", prime_arg, client_name, ret.code); - log_done("kadm5_create_principal", prime_arg, + log_done("kadm5_create_principal", prime_arg, errmsg ? errmsg : "success", client_name, service_name, client_addr(rqstp, buf)); - if (errmsg != NULL) + if (errmsg != NULL) krb5_free_error_message(handle ? handle->context : NULL, errmsg); - if (policy_migrate && (ret.code == 0)) { - arg->rec.policy = strdup("default"); - if ((arg->mask & KADM5_PW_EXPIRATION)) { - arg->mask = 0; - arg->mask |= KADM5_POLICY; - arg->mask |= KADM5_PW_EXPIRATION; - } else { - arg->mask = 0; - arg->mask |= KADM5_POLICY; - } - - retval = kadm5_modify_principal((void *)handle, - &arg->rec, arg->mask); - log_done("kadm5_modify_principal", - prime_arg, ((retval == 0) ? "success" : - error_message(retval)), client_name, - service_name, client_addr(rqstp, buf)); + if (policy_migrate && (ret.code == 0)) { + arg->rec.policy = strdup("default"); + if ((arg->mask & KADM5_PW_EXPIRATION)) { + arg->mask = 0; + arg->mask |= KADM5_POLICY; + arg->mask |= KADM5_PW_EXPIRATION; + } else { + arg->mask = 0; + arg->mask |= KADM5_POLICY; } + + retval = kadm5_modify_principal((void *)handle, + &arg->rec, arg->mask); + log_done("kadm5_modify_principal", + prime_arg, ((retval == 0) ? "success" : + error_message(retval)), client_name, + service_name, client_addr(rqstp, buf)); } + } error: if (name) diff --git a/usr/src/cmd/krb5/klist/klist.c b/usr/src/cmd/krb5/klist/klist.c index 22c9a152ef..00fa45cfe4 100644 --- a/usr/src/cmd/krb5/klist/klist.c +++ b/usr/src/cmd/krb5/klist/klist.c @@ -2,7 +2,6 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * clients/klist/klist.c @@ -632,7 +631,7 @@ show_credential(cred) fputs("\t",stdout); else fputs(", ",stdout); - fputs(gettext("renew until "), stdout); + fputs(gettext("renew until "), stdout); printtime(cred->times.renew_till); extra_field += 2; } diff --git a/usr/src/cmd/krb5/krb5kdc/do_as_req.c b/usr/src/cmd/krb5/krb5kdc/do_as_req.c index 4c415006ad..ed7383aebc 100644 --- a/usr/src/cmd/krb5/krb5kdc/do_as_req.c +++ b/usr/src/cmd/krb5/krb5kdc/do_as_req.c @@ -477,19 +477,19 @@ errout: free_padata_context(kdc_context, &pa_context); if (status) { - const char * emsg = 0; + const char *emsg = NULL; if (errcode) emsg = krb5_get_error_message (kdc_context, errcode); - audit_krb5kdc_as_req(&from_in4, (in_port_t)from->port, - 0, cname, sname, errcode); + audit_krb5kdc_as_req(&from_in4, (in_port_t)from->port, + 0, cname, sname, errcode); krb5_klog_syslog(LOG_INFO, "AS_REQ (%s) %s: %s: %s for %s%s%s", - ktypestr, - fromstring, status, - cname ? cname : "<unknown client>", - sname ? sname : "<unknown server>", - errcode ? ", " : "", - errcode ? emsg : ""); + ktypestr, + fromstring, status, + cname ? cname : "<unknown client>", + sname ? sname : "<unknown server>", + errcode ? ", " : "", + errcode ? emsg : ""); if (errcode) krb5_free_error_message (kdc_context, emsg); } diff --git a/usr/src/cmd/nl/nl.c b/usr/src/cmd/nl/nl.c index d927172e86..9c5a5f045f 100644 --- a/usr/src/cmd/nl/nl.c +++ b/usr/src/cmd/nl/nl.c @@ -28,8 +28,6 @@ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <locale.h> #include <regexpr.h> #include <stdio.h> @@ -90,9 +88,7 @@ extern char *optarg; /* getopt support */ extern int optind; int -main(argc, argv) -int argc; -char *argv[]; +main(int argc, char *argv[]) { register int j; register int i = 0; @@ -139,7 +135,7 @@ char *argv[]; while (argc > 0) { while ((c = getopt(argc, argv, - "pb:d:f:h:i:l:n:s:v:w:")) != EOF) { + "pb:d:f:h:i:l:n:s:v:w:")) != EOF) { switch (c) { case 'h': @@ -157,7 +153,7 @@ char *argv[]; (void) strcpy(pat, optarg+1); header = 'h'; hexpbuf = - compile(pat, (char *)0, (char *)0); + compile(pat, NULL, NULL); if (regerrno) regerr(regerrno); break; @@ -183,7 +179,7 @@ char *argv[]; (void) strcpy(pat, optarg+1); body = 'b'; bexpbuf = - compile(pat, (char *)0, (char *)0); + compile(pat, NULL, NULL); if (regerrno) regerr(regerrno); break; @@ -209,7 +205,7 @@ char *argv[]; (void) strcpy(pat, optarg+1); footer = 'f'; fexpbuf = - compile(pat, (char *)0, (char *)0); + compile(pat, NULL, NULL); if (regerrno) regerr(regerrno); break; @@ -337,10 +333,10 @@ for (j = 1; j < argc; j++) { } pat[r] = '\0'; header = 'h'; - hexpbuf = - compile(pat, (char *)0, (char *)0); - if (regerrno) - regerr(regerrno); + hexpbuf = + compile(pat, NULL, NULL); + if (regerrno) + regerr(regerrno); break; case '\0': header = 'n'; @@ -371,10 +367,10 @@ for (j = 1; j < argc; j++) { } pat[r] = '\0'; body = 'b'; - bexpbuf = - compile(pat, (char *)0, (char *)0); - if (regerrno) - regerr(regerrno); + bexpbuf = + compile(pat, NULL, NULL); + if (regerrno) + regerr(regerrno); break; case '\0': body = 't'; @@ -405,10 +401,10 @@ for (j = 1; j < argc; j++) { } pat[r] = '\0'; footer = 'f'; - fexpbuf = - compile(pat, (char *)0, (char *)0); - if (regerrno) - regerr(regerrno); + fexpbuf = + compile(pat, NULL, NULL); + if (regerrno) + regerr(regerrno); break; case '\0': footer = 'n'; @@ -653,20 +649,17 @@ for (j = 1; j < argc; j++) { /* REGEXP ERR ROUTINE */ static void -regerr(c) -int c; +regerr(int c) { (void) fprintf(stderr, gettext( - "nl: invalid regular expression: error code %d\n"), c); + "nl: invalid regular expression: error code %d\n"), c); exit(1); } /* CALCULATE NUMBER ROUTINE */ static void -pnum(n, sep) -int n; -char * sep; +pnum(int n, char *sep) { register int i; @@ -689,8 +682,7 @@ char * sep; /* IF NUM > 10, THEN USE THIS CALCULATE ROUTINE */ static void -num(v, p) -int v, p; +num(int v, int p) { if (v < 10) nbuf[p] = v + '0'; @@ -705,9 +697,7 @@ int v, p; #ifdef XPG4 static int -convert(c, option_arg) -int c; -char *option_arg; +convert(int c, char *option_arg) { s = option_arg; q = r = 0; @@ -726,23 +716,19 @@ char *option_arg; #else /* Solaris version */ static int -convert(argv) -char *argv; +convert(char *argv) { s = (char *)argv; q = 2; r = 0; while (s[q] != '\0') { - if (s[q] >= '0' && s[q] <= '9') - { - s1[r] = s[q]; - r++; - q++; + if (s[q] >= '0' && s[q] <= '9') { + s1[r] = s[q]; + r++; + q++; + } else { + optmsg(argv); } - else - { - optmsg(argv); - } } s1[r] = '\0'; k = atoi(s1); @@ -753,9 +739,7 @@ char *argv; /* CALCULATE NUM/TEXT SEPRATOR */ static void -npad(width, sep) - int width; - char * sep; +npad(int width, char *sep) { register int i; @@ -764,19 +748,17 @@ npad(width, sep) nbuf[i] = pad; (void) printf("%s", nbuf); - for (i = 0; i < (int) strlen(sep); i++) + for (i = 0; i < (int)strlen(sep); i++) (void) printf(" "); } #ifdef XPG4 static void -optmsg(option, option_arg) -int option; -char *option_arg; +optmsg(int option, char *option_arg) { if (option_arg != (char *)NULL) { (void) fprintf(stderr, gettext( - "nl: invalid option (-%c %s)\n"), option, option_arg); + "nl: invalid option (-%c %s)\n"), option, option_arg); } /* else getopt() will print illegal option message */ usage(); @@ -784,11 +766,9 @@ char *option_arg; #else /* Solaris version */ static void -optmsg(option) -char *option; +optmsg(char *option) { - (void) fprintf(stderr, gettext( - "nl: invalid option (%s)\n"), option); + (void) fprintf(stderr, gettext("nl: invalid option (%s)\n"), option); usage(); } #endif diff --git a/usr/src/common/nvpair/nvpair.c b/usr/src/common/nvpair/nvpair.c index ca370b1874..5881ba54b7 100644 --- a/usr/src/common/nvpair/nvpair.c +++ b/usr/src/common/nvpair/nvpair.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2016 by Delphix. All rights reserved. + * Copyright (c) 2015, 2017 by Delphix. All rights reserved. */ #include <sys/stropts.h> @@ -2195,8 +2195,10 @@ nvs_embedded(nvstream_t *nvs, nvlist_t *embedded) nvlist_init(embedded, embedded->nvl_nvflag, priv); - if (nvs->nvs_recursion >= nvpair_max_recursion) + if (nvs->nvs_recursion >= nvpair_max_recursion) { + nvlist_free(embedded); return (EINVAL); + } nvs->nvs_recursion++; if ((err = nvs_operation(nvs, embedded, NULL)) != 0) nvlist_free(embedded); diff --git a/usr/src/lib/libc/makelibccatalog.sh b/usr/src/lib/libc/makelibccatalog.sh index 9f765532ad..3536f3af26 100644 --- a/usr/src/lib/libc/makelibccatalog.sh +++ b/usr/src/lib/libc/makelibccatalog.sh @@ -91,7 +91,7 @@ done # # Change Directory # - cd ../locale + cd ../regex rm -f messages.po regerror.po ${XGETTEXT} -a regerror.c diff --git a/usr/src/man/man9f/ddi_periodic_add.9f b/usr/src/man/man9f/ddi_periodic_add.9f index 7b865acbb8..72b7430190 100644 --- a/usr/src/man/man9f/ddi_periodic_add.9f +++ b/usr/src/man/man9f/ddi_periodic_add.9f @@ -4,7 +4,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. .\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with .\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_PERIODIC_ADD 9F "Jul 23, 2013" +.TH DDI_PERIODIC_ADD 9F "May 04, 2017" .SH NAME ddi_periodic_add \- request periodic function invocation .SH SYNOPSIS diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index 7d2637a592..62cc59b17a 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -154,6 +154,7 @@ file path=opt/zfs-tests/README mode=0444 file path=opt/zfs-tests/bin/chg_usr_exec mode=0555 file path=opt/zfs-tests/bin/devname2devid mode=0555 file path=opt/zfs-tests/bin/dir_rd_update mode=0555 +file path=opt/zfs-tests/bin/dos_ro mode=0555 file path=opt/zfs-tests/bin/file_check mode=0555 file path=opt/zfs-tests/bin/file_trunc mode=0555 file path=opt/zfs-tests/bin/file_write mode=0555 @@ -186,6 +187,7 @@ file path=opt/zfs-tests/tests/functional/acl/cifs/cifs.kshlib mode=0444 file path=opt/zfs-tests/tests/functional/acl/cifs/cifs_attr_001_pos mode=0555 file path=opt/zfs-tests/tests/functional/acl/cifs/cifs_attr_002_pos mode=0555 file path=opt/zfs-tests/tests/functional/acl/cifs/cifs_attr_003_pos mode=0555 +file path=opt/zfs-tests/tests/functional/acl/cifs/cifs_attr_004_pos mode=0555 file path=opt/zfs-tests/tests/functional/acl/cifs/cleanup mode=0555 file path=opt/zfs-tests/tests/functional/acl/cifs/setup mode=0555 file path=opt/zfs-tests/tests/functional/acl/nontrivial/cleanup mode=0555 diff --git a/usr/src/test/Makefile.com b/usr/src/test/Makefile.com index aabe39d22b..49e23dd496 100644 --- a/usr/src/test/Makefile.com +++ b/usr/src/test/Makefile.com @@ -30,6 +30,10 @@ lint_SRCS: $(LINT.c) $(SRCS) $(LDLIBS) $(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) + @if [ -f $@/Makefile ]; then \ + cd $@; pwd; $(MAKE) $(TARGET); \ + else \ + true; \ + fi FRC: diff --git a/usr/src/test/zfs-tests/cmd/dos_ro/Makefile b/usr/src/test/zfs-tests/cmd/dos_ro/Makefile new file mode 100644 index 0000000000..642de01e59 --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/dos_ro/Makefile @@ -0,0 +1,22 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +PROG = dos_ro + +include $(SRC)/cmd/Makefile.cmd + +LDLIBS += -lnvpair + +include ../Makefile.subdirs diff --git a/usr/src/test/zfs-tests/cmd/dos_ro/dos_ro.c b/usr/src/test/zfs-tests/cmd/dos_ro/dos_ro.c new file mode 100644 index 0000000000..4f0510f72b --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/dos_ro/dos_ro.c @@ -0,0 +1,143 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <attr.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <libnvpair.h> + +extern const char *__progname; + +int vflag = 0; + +static int +dosattr_set_ro(int fildes, const char *fname) +{ + nvlist_t *nvl = NULL; + int err; + + err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); + if (err != 0) + return (err); + + (void) nvlist_add_boolean_value(nvl, A_READONLY, 1); + + if (fname == NULL) { + err = fsetattr(fildes, XATTR_VIEW_READWRITE, nvl); + } else { + err = setattrat(fildes, XATTR_VIEW_READWRITE, fname, nvl); + } + if (err < 0) { + err = errno; + if (vflag > 1) { + (void) fprintf(stderr, + "dosattr_set: setattrat (%s), err %d\n", + fname, err); + } + } + + nvlist_free(nvl); + + return (err); +} + +void +usage(void) +{ + (void) fprintf(stderr, "usage: %s [-v] file\n", + __progname); + exit(1); +} + +int +main(int argc, char **argv) +{ + char *fname; + int c, fd, n; + + while ((c = getopt(argc, argv, "v")) != -1) { + switch (c) { + case 'v': + vflag++; + break; + case '?': + default: + usage(); + break; + } + } + + if (optind + 1 != argc) + usage(); + fname = argv[optind]; + + fd = open(fname, O_CREAT | O_RDWR, 0644); + if (fd < 0) { + perror(fname); + exit(1); + } + + if (vflag) + (void) fprintf(stderr, "Write 1 (mode 644)\n"); + n = write(fd, "mode 644 OK\n", 12); + if (n != 12) { + (void) fprintf(stderr, "write mode 644, err=%d\n", errno); + exit(1); + } + + if (vflag) + (void) fprintf(stderr, "Chmod 444\n"); + n = fchmod(fd, 0444); + if (n < 0) { + (void) fprintf(stderr, "chmod 444, err=%d\n", errno); + exit(1); + } + + if (vflag) + (void) fprintf(stderr, "Write 2 (mode 444)\n"); + n = write(fd, "mode 444 OK\n", 12); + if (n != 12) { + (void) fprintf(stderr, "write mode 444, err=%d\n", errno); + exit(1); + } + + if (vflag) + (void) fprintf(stderr, "Set DOS R/O\n"); + n = dosattr_set_ro(fd, NULL /* fname? */); + if (n != 0) { + (void) fprintf(stderr, "Set R/O, err=%d\n", n); + exit(1); + } + + /* + * This fails, but write on an already open handle should succeed + * the same as when we've set the mode to 444 after open. + */ + if (vflag) + (void) fprintf(stderr, "Write 3 (DOS R/O)\n"); + n = write(fd, "Write DOS RO?\n", 14); + if (n != 14) { + (void) fprintf(stderr, "write (DOS R/O), err=%d\n", errno); + exit(1); + } + + return (0); +} diff --git a/usr/src/test/zfs-tests/include/commands.cfg b/usr/src/test/zfs-tests/include/commands.cfg index afc3153e6e..462f0e55e3 100644 --- a/usr/src/test/zfs-tests/include/commands.cfg +++ b/usr/src/test/zfs-tests/include/commands.cfg @@ -172,6 +172,7 @@ export SBIN_FILES='fdisk export ZFSTEST_FILES='chg_usr_exec devname2devid dir_rd_update + dos_ro file_check file_trunc file_write diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run index df1b6369b3..aaeb65de38 100644 --- a/usr/src/test/zfs-tests/runfiles/delphix.run +++ b/usr/src/test/zfs-tests/runfiles/delphix.run @@ -25,7 +25,8 @@ post = cleanup outputdir = /var/tmp/test_results [/opt/zfs-tests/tests/functional/acl/cifs] -tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos'] +tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos', + 'cifs_attr_004_pos'] [/opt/zfs-tests/tests/functional/acl/nontrivial] tests = ['zfs_acl_chmod_001_neg', 'zfs_acl_chmod_002_pos', diff --git a/usr/src/test/zfs-tests/runfiles/omnios.run b/usr/src/test/zfs-tests/runfiles/omnios.run index 952ab1503d..df7dbb2d0e 100644 --- a/usr/src/test/zfs-tests/runfiles/omnios.run +++ b/usr/src/test/zfs-tests/runfiles/omnios.run @@ -25,7 +25,8 @@ post = cleanup outputdir = /var/tmp/test_results [/opt/zfs-tests/tests/functional/acl/cifs] -tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos'] +tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos', + 'cifs_attr_004_pos'] [/opt/zfs-tests/tests/functional/acl/nontrivial] tests = ['zfs_acl_chmod_001_neg', 'zfs_acl_chmod_002_pos', diff --git a/usr/src/test/zfs-tests/runfiles/openindiana.run b/usr/src/test/zfs-tests/runfiles/openindiana.run index 407af74e57..81672aac69 100644 --- a/usr/src/test/zfs-tests/runfiles/openindiana.run +++ b/usr/src/test/zfs-tests/runfiles/openindiana.run @@ -25,7 +25,8 @@ post = cleanup outputdir = /var/tmp/test_results [/opt/zfs-tests/tests/functional/acl/cifs] -tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos'] +tests = ['cifs_attr_001_pos', 'cifs_attr_002_pos', 'cifs_attr_003_pos', + 'cifs_attr_004_pos'] [/opt/zfs-tests/tests/functional/acl/nontrivial] tests = ['zfs_acl_chmod_001_neg', 'zfs_acl_chmod_002_pos', diff --git a/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_003_pos.ksh b/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_003_pos.ksh index a47ad0277b..09ddc4281a 100644 --- a/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_003_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_003_pos.ksh @@ -376,6 +376,7 @@ function unit_writeacl function test_readonly { typeset object=$1 + typeset exp if [[ -z $object ]]; then log_fail "Object($object) not defined." @@ -394,14 +395,21 @@ function test_readonly log_must set_attribute $object "R" - unit_writefile $object $user 1 + # As with mode bits, root can bypass. + if [[ "$user" == "root" ]]; then + exp=0 + else + exp=1 + fi + + unit_writefile $object $user $exp unit_writedir $object $user - unit_appenddata $object $user 1 + unit_appenddata $object $user $exp if [[ -d $object ]]; then unit_writexattr $object $user else - unit_writexattr $object $user 1 + unit_writexattr $object $user $exp fi unit_accesstime $object $user diff --git a/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_004_pos.ksh b/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_004_pos.ksh new file mode 100644 index 0000000000..b5055544b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/acl/cifs/cifs_attr_004_pos.ksh @@ -0,0 +1,141 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +. $STF_SUITE/tests/functional/acl/acl_common.kshlib +. $STF_SUITE/tests/functional/acl/cifs/cifs.kshlib + +# +# DESCRIPTION: +# Verify the ability to continue writing to a file +# after opening the file read/write, and setting +# the DOS Readonly flag on that file. +# +# STRATEGY: +# Run the special program "dos_ro" + +verify_runnable "both" + +function cleanup +{ + if [[ -n $gobject ]]; then + destroy_object $gobject + fi + + for fs in $TESTPOOL/$TESTFS $TESTPOOL ; do + mtpt=$(get_prop mountpoint $fs) + log_must rm -rf $mtpt/file.* $mtpt/dir.* + done + + [[ -f $TESTFILE ]] && rm $TESTFILE +} + +# +# Set the special attribute to the given node +# +# $1: The given node (file/dir) +# $2: The special attribute to be set +# +function set_attribute +{ + typeset object=$1 + typeset attr=$2 + + if [[ -z $attr ]]; then + attr="AHRSadimu" + if [[ -f $object ]]; then + attr="${attr}q" + fi + fi + chmod S+c${attr} $object + return $? +} + +# +# Clear the special attribute to the given node +# +# $1: The given node (file/dir) +# $2: The special attribute to be cleared +# +function clear_attribute +{ + typeset object=$1 + typeset attr=$2 + + if [[ -z $attr ]]; then + if is_global_zone ; then + attr="AHRSadimu" + if [[ -f $object ]]; then + attr="${attr}q" + fi + else + attr="AHRS" + fi + fi + + chmod S-c${attr} $object + return $? +} + +FILES="file.0 file.1" +FS="$TESTPOOL $TESTPOOL/$TESTFS" +ATTRS="R" + +TESTFILE=/tmp/tfile +TESTDIR=tdir +TESTATTR=tattr +TESTACL=user:$ZFS_ACL_OTHER1:write_data:allow +TESTMODE=777 +TESTSTR="ZFS test suites" + +log_assert "Verify writable open handle still works after " \ + "setting the DOS Readonly flag on a file." +log_onexit cleanup + +echo "$TESTSTR" > $TESTFILE + +typeset gobject +typeset gattr +for fs in $FS ; do + mtpt=$(get_prop mountpoint $fs) + chmod 777 $mtpt + for user in root $ZFS_ACL_STAFF1; do + log_must set_cur_usr $user + for file in $FILES ; do + gobject=$mtpt/$file + create_object "file" $gobject $ZFS_ACL_CUR_USER + log_must dos_ro $gobject + destroy_object $gobject + done + done +done + +log_pass "Writable handle OK after setting DOS R/O flag." diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c index 58177cd7df..0acd1302fc 100644 --- a/usr/src/uts/common/fs/zfs/arc.c +++ b/usr/src/uts/common/fs/zfs/arc.c @@ -1076,6 +1076,7 @@ typedef struct l2arc_read_callback { blkptr_t l2rcb_bp; /* original blkptr */ zbookmark_phys_t l2rcb_zb; /* original bookmark */ int l2rcb_flags; /* original flags */ + abd_t *l2rcb_abd; /* temporary buffer */ } l2arc_read_callback_t; typedef struct l2arc_write_callback { @@ -5049,6 +5050,8 @@ top: !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) && !(l2arc_noprefetch && HDR_PREFETCH(hdr))) { l2arc_read_callback_t *cb; + abd_t *abd; + uint64_t asize; DTRACE_PROBE1(l2arc__hit, arc_buf_hdr_t *, hdr); ARCSTAT_BUMP(arcstat_l2_hits); @@ -5060,8 +5063,17 @@ top: cb->l2rcb_zb = *zb; cb->l2rcb_flags = zio_flags; + asize = vdev_psize_to_asize(vd, size); + if (asize != size) { + abd = abd_alloc_for_io(asize, + HDR_ISTYPE_METADATA(hdr)); + cb->l2rcb_abd = abd; + } else { + abd = hdr->b_l1hdr.b_pabd; + } + ASSERT(addr >= VDEV_LABEL_START_SIZE && - addr + lsize < vd->vdev_psize - + addr + asize <= vd->vdev_psize - VDEV_LABEL_END_SIZE); /* @@ -5073,7 +5085,7 @@ top: ASSERT3U(HDR_GET_COMPRESS(hdr), !=, ZIO_COMPRESS_EMPTY); rzio = zio_read_phys(pio, vd, addr, - size, hdr->b_l1hdr.b_pabd, + asize, abd, ZIO_CHECKSUM_OFF, l2arc_read_done, cb, priority, zio_flags | ZIO_FLAG_DONT_CACHE | @@ -6575,6 +6587,33 @@ l2arc_read_done(zio_t *zio) mutex_enter(hash_lock); ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); + /* + * If the data was read into a temporary buffer, + * move it and free the buffer. + */ + if (cb->l2rcb_abd != NULL) { + ASSERT3U(arc_hdr_size(hdr), <, zio->io_size); + if (zio->io_error == 0) { + abd_copy(hdr->b_l1hdr.b_pabd, cb->l2rcb_abd, + arc_hdr_size(hdr)); + } + + /* + * The following must be done regardless of whether + * there was an error: + * - free the temporary buffer + * - point zio to the real ARC buffer + * - set zio size accordingly + * These are required because zio is either re-used for + * an I/O of the block in the case of the error + * or the zio is passed to arc_read_done() and it + * needs real data. + */ + abd_free(cb->l2rcb_abd); + zio->io_size = zio->io_orig_size = arc_hdr_size(hdr); + zio->io_abd = zio->io_orig_abd = hdr->b_l1hdr.b_pabd; + } + ASSERT3P(zio->io_abd, !=, NULL); /* @@ -6912,23 +6951,34 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) * Normally the L2ARC can use the hdr's data, but if * we're sharing data between the hdr and one of its * bufs, L2ARC needs its own copy of the data so that - * the ZIO below can't race with the buf consumer. To - * ensure that this copy will be available for the + * the ZIO below can't race with the buf consumer. + * Another case where we need to create a copy of the + * data is when the buffer size is not device-aligned + * and we need to pad the block to make it such. + * That also keeps the clock hand suitably aligned. + * + * To ensure that the copy will be available for the * lifetime of the ZIO and be cleaned up afterwards, we * add it to the l2arc_free_on_write queue. */ + uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, + size); abd_t *to_write; - if (!HDR_SHARED_DATA(hdr)) { + if (!HDR_SHARED_DATA(hdr) && size == asize) { to_write = hdr->b_l1hdr.b_pabd; } else { - to_write = abd_alloc_for_io(size, + to_write = abd_alloc_for_io(asize, HDR_ISTYPE_METADATA(hdr)); abd_copy(to_write, hdr->b_l1hdr.b_pabd, size); + if (asize != size) { + abd_zero_off(to_write, size, + asize - size); + } l2arc_free_abd_on_write(to_write, size, arc_buf_type(hdr)); } wzio = zio_write_phys(pio, dev->l2ad_vdev, - hdr->b_l2hdr.b_daddr, size, to_write, + hdr->b_l2hdr.b_daddr, asize, to_write, ZIO_CHECKSUM_OFF, NULL, hdr, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_CANFAIL, B_FALSE); @@ -6938,11 +6988,6 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) zio_t *, wzio); write_asize += size; - /* - * Keep the clock hand suitably device-aligned. - */ - uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, - size); write_psize += asize; dev->l2ad_hand += asize; diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c index f2ef7e5134..519b4355d5 100644 --- a/usr/src/uts/common/fs/zfs/zfs_acl.c +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> @@ -2035,13 +2035,11 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) } /* - * Only check for READONLY on non-directories. + * Intentionally allow ZFS_READONLY through here. + * See zfs_zaccess_common(). */ if ((v4_mode & WRITE_MASK_DATA) && - (((ZTOV(zp)->v_type != VDIR) && - (zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) || - (ZTOV(zp)->v_type == VDIR && - (zp->z_pflags & ZFS_IMMUTABLE)))) { + (zp->z_pflags & ZFS_IMMUTABLE)) { return (SET_ERROR(EPERM)); } @@ -2253,6 +2251,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, return (0); } + /* + * Note: ZFS_READONLY represents the "DOS R/O" attribute. + * When that flag is set, we should behave as if write access + * were not granted by anything in the ACL. In particular: + * We _must_ allow writes after opening the file r/w, then + * setting the DOS R/O attribute, and writing some more. + * (Similar to how you can write after fchmod(fd, 0444).) + * + * Therefore ZFS_READONLY is ignored in the dataset check + * above, and checked here as if part of the ACL check. + * Also note: DOS R/O is ignored for directories. + */ + if ((v4_mode & WRITE_MASK_DATA) && + (ZTOV(zp)->v_type != VDIR) && + (zp->z_pflags & ZFS_READONLY)) { + return (SET_ERROR(EPERM)); + } + return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); } diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c index efe36b7f10..cebd796a1f 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vnops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c @@ -719,9 +719,11 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) } /* - * If immutable or not appending then return EPERM + * If immutable or not appending then return EPERM. + * Intentionally allow ZFS_READONLY through here. + * See zfs_zaccess_common() */ - if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || + if ((zp->z_pflags & ZFS_IMMUTABLE) || ((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) && (uio->uio_loffset < zp->z_size))) { ZFS_EXIT(zfsvfs); @@ -2793,10 +2795,9 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, return (SET_ERROR(EPERM)); } - if ((mask & AT_SIZE) && (zp->z_pflags & ZFS_READONLY)) { - ZFS_EXIT(zfsvfs); - return (SET_ERROR(EPERM)); - } + /* + * Note: ZFS_READONLY is handled in zfs_zaccess_common. + */ /* * Verify timestamps doesn't overflow 32 bits. @@ -4701,8 +4702,12 @@ zfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); + /* + * Note: ZFS_READONLY is handled in zfs_zaccess_common. + */ + if ((prot & PROT_WRITE) && (zp->z_pflags & - (ZFS_IMMUTABLE | ZFS_READONLY | ZFS_APPENDONLY))) { + (ZFS_IMMUTABLE | ZFS_APPENDONLY))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } diff --git a/usr/src/uts/common/rpc/auth_sys.h b/usr/src/uts/common/rpc/auth_sys.h index 5f163d270b..ef66402245 100644 --- a/usr/src/uts/common/rpc/auth_sys.h +++ b/usr/src/uts/common/rpc/auth_sys.h @@ -116,8 +116,8 @@ extern bool_t xdr_gid_t(XDR *, gid_t *); extern bool_t xdr_uid_t(XDR *, uid_t *); #ifdef _KERNEL -extern bool_t xdr_authkern(XDR *); -extern bool_t xdr_authloopback(XDR *); +extern bool_t xdr_authkern(XDR *, cred_t *); +extern bool_t xdr_authloopback(XDR *, cred_t *); extern enum auth_stat _svcauth_unix(struct svc_req *, struct rpc_msg *); extern enum auth_stat _svcauth_short(struct svc_req *, struct rpc_msg *); #endif diff --git a/usr/src/uts/common/rpc/sec/auth_kern.c b/usr/src/uts/common/rpc/sec/auth_kern.c index e045c1c08f..2c3286d35d 100644 --- a/usr/src/uts/common/rpc/sec/auth_kern.c +++ b/usr/src/uts/common/rpc/sec/auth_kern.c @@ -120,78 +120,117 @@ authkern_marshal(AUTH *auth, XDR *xdrs, struct cred *cr) { char *sercred; XDR xdrm; - struct opaque_auth *cred; - bool_t ret = FALSE; - const gid_t *gp, *gpend; - int gidlen, credsize, namelen, rounded_namelen; + bool_t ret; + uint32_t gidlen, credsize, namelen, rounded_namelen; int32_t *ptr; char *nodename = uts_nodename(); + uint_t startpos; + + ASSERT(xdrs->x_op == XDR_ENCODE); + ASSERT(auth->ah_cred.oa_flavor == AUTH_SYS); + ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE); + ASSERT(auth->ah_verf.oa_length == 0); /* * First we try a fast path to get through * this very common operation. */ - gp = crgetgroups(cr); + namelen = (uint32_t)strlen(nodename); + if (namelen > MAX_MACHINE_NAME) + return (FALSE); + rounded_namelen = RNDUP(namelen); + + /* + * NFIELDS is a number of the following fields we are going to encode: + * - stamp + * - strlen(machinename) + * - uid + * - gid + * - the number of gids + */ +#define NFIELDS 5 + CTASSERT((NFIELDS + NGRPS) * BYTES_PER_XDR_UNIT + + RNDUP(MAX_MACHINE_NAME) <= MAX_AUTH_BYTES); + gidlen = crgetngroups(cr); if (gidlen > NGRPS) gidlen = NGRPS; - gpend = &gp[gidlen-1]; - namelen = (int)strlen(nodename); - rounded_namelen = RNDUP(namelen); - credsize = 4 + 4 + rounded_namelen + 4 + 4 + 4 + gidlen * 4; - ptr = XDR_INLINE(xdrs, 4 + 4 + credsize + 4 + 4); - if (ptr) { + credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen + + gidlen * BYTES_PER_XDR_UNIT; + ASSERT(credsize <= MAX_AUTH_BYTES); +#undef NFIELDS + + /* + * We need to marshal both cred and verf parts of the rpc_msg body + * (call_body). For the cred part we need to inline the auth_flavor + * and the opaque auth body size. Then we inline the credsize bytes of + * the opaque auth body for the cred part. Finally we add the + * AUTH_NONE verifier (its auth_flavor and the opaque auth body size). + */ + ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize + + 2 * BYTES_PER_XDR_UNIT); + if (ptr != NULL) { /* * We can do the fast path. */ - IXDR_PUT_INT32(ptr, AUTH_UNIX); /* cred flavor */ - IXDR_PUT_INT32(ptr, credsize); /* cred len */ + const gid_t *gp = crgetgroups(cr); + + IXDR_PUT_U_INT32(ptr, AUTH_SYS); /* cred flavor */ + IXDR_PUT_U_INT32(ptr, credsize); /* cred len */ + IXDR_PUT_INT32(ptr, gethrestime_sec()); - IXDR_PUT_INT32(ptr, namelen); - bcopy(nodename, (caddr_t)ptr, namelen); - if (rounded_namelen - namelen) - bzero(((caddr_t)ptr) + namelen, - rounded_namelen - namelen); + IXDR_PUT_U_INT32(ptr, namelen); + bcopy(nodename, ptr, namelen); + if ((rounded_namelen - namelen) > 0) + bzero((char *)ptr + namelen, rounded_namelen - namelen); ptr += rounded_namelen / BYTES_PER_XDR_UNIT; - IXDR_PUT_INT32(ptr, crgetuid(cr)); - IXDR_PUT_INT32(ptr, crgetgid(cr)); - IXDR_PUT_INT32(ptr, gidlen); - while (gp <= gpend) { - IXDR_PUT_INT32(ptr, *gp++); - } - IXDR_PUT_INT32(ptr, AUTH_NULL); /* verf flavor */ - IXDR_PUT_INT32(ptr, 0); /* verf len */ + IXDR_PUT_U_INT32(ptr, crgetuid(cr)); + IXDR_PUT_U_INT32(ptr, crgetgid(cr)); + IXDR_PUT_U_INT32(ptr, gidlen); + while (gidlen-- > 0) + IXDR_PUT_U_INT32(ptr, *gp++); + + IXDR_PUT_U_INT32(ptr, AUTH_NULL); /* verf flavor */ + IXDR_PUT_U_INT32(ptr, 0); /* verf len */ + return (TRUE); } + sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP); + /* - * serialize u struct stuff into sercred + * Serialize the auth body data into sercred. */ xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE); - if (!xdr_authkern(&xdrm)) { + startpos = XDR_GETPOS(&xdrm); + if (!xdr_authkern(&xdrm, cr)) { printf("authkern_marshal: xdr_authkern failed\n"); ret = FALSE; goto done; } /* - * Make opaque auth credentials that point at serialized u struct + * Make opaque auth credentials to point at the serialized auth body + * data. */ - cred = &(auth->ah_cred); - cred->oa_length = XDR_GETPOS(&xdrm); - cred->oa_base = sercred; + auth->ah_cred.oa_base = sercred; + auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos; + ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES); /* - * serialize credentials and verifiers (null) + * serialize credentials and verifier (null) */ if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) && (xdr_opaque_auth(xdrs, &(auth->ah_verf)))) ret = TRUE; else ret = FALSE; + done: + XDR_DESTROY(&xdrm); kmem_free(sercred, MAX_AUTH_BYTES); + return (ret); } diff --git a/usr/src/uts/common/rpc/sec/auth_loopb.c b/usr/src/uts/common/rpc/sec/auth_loopb.c index 8e4e4522ad..ab5318162b 100644 --- a/usr/src/uts/common/rpc/sec/auth_loopb.c +++ b/usr/src/uts/common/rpc/sec/auth_loopb.c @@ -32,8 +32,6 @@ * under license from the Regents of the University of California. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * auth_loopb.c, implements UNIX style authentication parameters in the * kernel. Interfaces with svc_auth_loopback on the server. See @@ -124,77 +122,120 @@ authloopback_marshal(AUTH *auth, XDR *xdrs, struct cred *cr) { char *sercred; XDR xdrm; - struct opaque_auth *cred; - bool_t ret = FALSE; - const gid_t *gp, *gpend; - int gidlen, credsize, namelen, rounded_namelen; + bool_t ret; + uint32_t gidlen, credsize, namelen, rounded_namelen; int32_t *ptr; + char *nodename = uts_nodename(); + uint32_t maxgidlen; + uint_t startpos; + + ASSERT(xdrs->x_op == XDR_ENCODE); + ASSERT(auth->ah_cred.oa_flavor == AUTH_LOOPBACK); + ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE); + ASSERT(auth->ah_verf.oa_length == 0); /* * First we try a fast path to get through * this very common operation. */ - gp = crgetgroups(cr); + namelen = (uint32_t)strlen(nodename); + if (namelen > MAX_MACHINE_NAME) + return (FALSE); + rounded_namelen = RNDUP(namelen); + + /* + * NFIELDS is a number of the following fields we are going to encode: + * - stamp + * - strlen(machinename) + * - uid + * - gid + * - the number of gids + */ +#define NFIELDS 5 + CTASSERT(NFIELDS * BYTES_PER_XDR_UNIT + RNDUP(MAX_MACHINE_NAME) <= + MAX_AUTH_BYTES); + maxgidlen = (MAX_AUTH_BYTES - NFIELDS * BYTES_PER_XDR_UNIT - + rounded_namelen) / BYTES_PER_XDR_UNIT; + gidlen = crgetngroups(cr); - if (gidlen > NGRPS_LOOPBACK) + if (gidlen > maxgidlen) return (FALSE); - gpend = &gp[gidlen-1]; - namelen = (int)strlen(uts_nodename()); - rounded_namelen = RNDUP(namelen); - credsize = 4 + 4 + rounded_namelen + 4 + 4 + 4 + gidlen * 4; - ptr = XDR_INLINE(xdrs, 4 + 4 + credsize + 4 + 4); - if (ptr) { + credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen + + gidlen * BYTES_PER_XDR_UNIT; + ASSERT(credsize <= MAX_AUTH_BYTES); +#undef NFIELDS + + /* + * We need to marshal both cred and verf parts of the rpc_msg body + * (call_body). For the cred part we need to inline the auth_flavor + * and the opaque auth body size. Then we inline the credsize bytes of + * the opaque auth body for the cred part. Finally we add the + * AUTH_NONE verifier (its auth_flavor and the opaque auth body size). + */ + ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize + + 2 * BYTES_PER_XDR_UNIT); + if (ptr != NULL) { /* * We can do the fast path. */ - IXDR_PUT_INT32(ptr, AUTH_LOOPBACK); /* cred flavor */ - IXDR_PUT_INT32(ptr, credsize); /* cred len */ + const gid_t *gp = crgetgroups(cr); + + IXDR_PUT_U_INT32(ptr, AUTH_LOOPBACK); /* cred flavor */ + IXDR_PUT_U_INT32(ptr, credsize); /* cred len */ + IXDR_PUT_INT32(ptr, gethrestime_sec()); - IXDR_PUT_INT32(ptr, namelen); - bcopy(uts_nodename(), ptr, namelen); - if (rounded_namelen - namelen) - bzero(((caddr_t)ptr) + namelen, - rounded_namelen - namelen); + IXDR_PUT_U_INT32(ptr, namelen); + bcopy(nodename, ptr, namelen); + if ((rounded_namelen - namelen) > 0) + bzero((char *)ptr + namelen, rounded_namelen - namelen); ptr += rounded_namelen / BYTES_PER_XDR_UNIT; - IXDR_PUT_INT32(ptr, crgetuid(cr)); - IXDR_PUT_INT32(ptr, crgetgid(cr)); - IXDR_PUT_INT32(ptr, gidlen); - while (gp <= gpend) { - IXDR_PUT_INT32(ptr, *gp++); - } - IXDR_PUT_INT32(ptr, AUTH_NULL); /* verf flavor */ - IXDR_PUT_INT32(ptr, 0); /* verf len */ + IXDR_PUT_U_INT32(ptr, crgetuid(cr)); + IXDR_PUT_U_INT32(ptr, crgetgid(cr)); + IXDR_PUT_U_INT32(ptr, gidlen); + while (gidlen-- > 0) + IXDR_PUT_U_INT32(ptr, *gp++); + + IXDR_PUT_U_INT32(ptr, AUTH_NONE); /* verf flavor */ + IXDR_PUT_U_INT32(ptr, 0); /* verf len */ + return (TRUE); } + sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP); + /* - * serialize u struct stuff into sercred + * Serialize the auth body data into sercred. */ xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE); - if (!xdr_authloopback(&xdrm)) { + startpos = XDR_GETPOS(&xdrm); + if (!xdr_authloopback(&xdrm, cr)) { printf("authloopback_marshal: xdr_authloopback failed\n"); ret = FALSE; goto done; } /* - * Make opaque auth credentials that point at serialized u struct + * Make opaque auth credentials to point at the serialized auth body + * data. */ - cred = &(auth->ah_cred); - cred->oa_length = XDR_GETPOS(&xdrm); - cred->oa_base = sercred; + auth->ah_cred.oa_base = sercred; + auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos; + ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES); /* - * serialize credentials and verifiers (null) + * serialize credentials and verifier (null) */ if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) && (xdr_opaque_auth(xdrs, &(auth->ah_verf)))) ret = TRUE; else ret = FALSE; + done: + XDR_DESTROY(&xdrm); kmem_free(sercred, MAX_AUTH_BYTES); + return (ret); } diff --git a/usr/src/uts/common/rpc/sec/authu_prot.c b/usr/src/uts/common/rpc/sec/authu_prot.c index dbc719e03c..8b0bf90a5d 100644 --- a/usr/src/uts/common/rpc/sec/authu_prot.c +++ b/usr/src/uts/common/rpc/sec/authu_prot.c @@ -110,20 +110,18 @@ xdr_gid_t(XDR *xdrs, gid_t *ip) * NOTE: this is an XDR_ENCODE only routine. */ bool_t -xdr_authkern(XDR *xdrs) +xdr_authkern(XDR *xdrs, cred_t *cr) { uid_t uid; gid_t gid; uint_t len; caddr_t groups; char *name = uts_nodename(); - struct cred *cr; time_t now; if (xdrs->x_op != XDR_ENCODE) return (FALSE); - cr = CRED(); uid = crgetuid(cr); gid = crgetgid(cr); len = crgetngroups(cr); @@ -137,8 +135,7 @@ xdr_authkern(XDR *xdrs) xdr_string(xdrs, &name, MAX_MACHINE_NAME) && xdr_uid_t(xdrs, &uid) && xdr_gid_t(xdrs, &gid) && - xdr_array(xdrs, &groups, &len, NGRPS, sizeof (int), - (xdrproc_t)xdr_int)) + xdr_array(xdrs, &groups, &len, NGRPS, sizeof (gid_t), xdr_gid_t)) return (TRUE); return (FALSE); } @@ -148,20 +145,18 @@ xdr_authkern(XDR *xdrs) * NOTE: this is an XDR_ENCODE only routine. */ bool_t -xdr_authloopback(XDR *xdrs) +xdr_authloopback(XDR *xdrs, cred_t *cr) { uid_t uid; gid_t gid; - int len; + uint_t len; caddr_t groups; char *name = uts_nodename(); - struct cred *cr; time_t now; if (xdrs->x_op != XDR_ENCODE) return (FALSE); - cr = CRED(); uid = crgetuid(cr); gid = crgetgid(cr); len = crgetngroups(cr); @@ -171,8 +166,8 @@ xdr_authloopback(XDR *xdrs) xdr_string(xdrs, &name, MAX_MACHINE_NAME) && xdr_uid_t(xdrs, &uid) && xdr_gid_t(xdrs, &gid) && - xdr_array(xdrs, &groups, (uint_t *)&len, NGRPS_LOOPBACK, - sizeof (int), (xdrproc_t)xdr_int)) + xdr_array(xdrs, &groups, &len, NGROUPS_UMAX, sizeof (gid_t), + xdr_gid_t)) return (TRUE); return (FALSE); } |
