diff options
author | jpk <none@none> | 2006-03-24 12:29:20 -0800 |
---|---|---|
committer | jpk <none@none> | 2006-03-24 12:29:20 -0800 |
commit | 45916cd2fec6e79bca5dee0421bd39e3c2910d1e (patch) | |
tree | 6b3ea6982435d47edc8972c72c62f9d111e8bb10 /usr/src/uts/common/fs/nfs/nfs_subr.c | |
parent | 2c9565cfcd87a2045c2e4b76f31ac4e978903589 (diff) | |
download | illumos-joyent-45916cd2fec6e79bca5dee0421bd39e3c2910d1e.tar.gz |
PSARC/2002/762 Layered Trusted Solaris
PSARC/2005/060 TSNET: Trusted Networking with Security Labels
PSARC/2005/259 Layered Trusted Solaris Label Interfaces
PSARC/2005/573 Solaris Trusted Extensions for Printing
PSARC/2005/691 Trusted Extensions for Device Allocation
PSARC/2005/723 Solaris Trusted Extensions Filesystem Labeling
PSARC/2006/009 Labeled Auditing
PSARC/2006/155 Trusted Extensions RBAC Changes
PSARC/2006/191 is_system_labeled
6293271 Zone processes should use zone_kcred instead of kcred
6394554 integrate Solaris Trusted Extensions
--HG--
rename : usr/src/cmd/dminfo/Makefile => deleted_files/usr/src/cmd/dminfo/Makefile
rename : usr/src/cmd/dminfo/dminfo.c => usr/src/cmd/allocate/dminfo.c
Diffstat (limited to 'usr/src/uts/common/fs/nfs/nfs_subr.c')
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs_subr.c | 161 |
1 files changed, 153 insertions, 8 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs_subr.c b/usr/src/uts/common/fs/nfs/nfs_subr.c index 8e1751a452..05e70935be 100644 --- a/usr/src/uts/common/fs/nfs/nfs_subr.c +++ b/usr/src/uts/common/fs/nfs/nfs_subr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. @@ -32,7 +31,7 @@ #include <sys/param.h> #include <sys/types.h> #include <sys/systm.h> -#include <sys/cred.h> +#include <sys/cred_impl.h> #include <sys/proc.h> #include <sys/user.h> #include <sys/time.h> @@ -61,6 +60,10 @@ #include <sys/callb.h> #include <sys/atomic.h> #include <sys/list.h> +#include <sys/tsol/tnet.h> +#include <sys/priv.h> + +#include <inet/ip6.h> #include <rpc/types.h> #include <rpc/xdr.h> @@ -279,6 +282,11 @@ extern void sec_clnt_freeh(AUTH *); extern void sec_clnt_freeinfo(struct sec_data *); /* + * used in mount policy + */ +extern ts_label_t *getflabel_cipso(vfs_t *); + +/* * EIO or EINTR are not recoverable errors. */ #define IS_RECOVERABLE_ERROR(error) !((error == EINTR) || (error == EIO)) @@ -914,17 +922,19 @@ rfs3call(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, static int rfscall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, - xdrproc_t xdrres, caddr_t resp, cred_t *cr, int *douprintf, + xdrproc_t xdrres, caddr_t resp, cred_t *icr, int *douprintf, enum clnt_stat *rpc_status, int flags, failinfo_t *fi) { CLIENT *client; struct chtab *ch; + cred_t *cr = icr; enum clnt_stat status; struct rpc_err rpcerr; struct timeval wait; int timeo; /* in units of hz */ int my_rsize, my_wsize; bool_t tryagain; + bool_t cred_cloned = FALSE; k_sigset_t smask; servinfo_t *svp; struct nfs_clnt *nfscl; @@ -1026,6 +1036,13 @@ failoverretry: } } + /* For TSOL, use a new cred which has net_mac_aware flag */ + if (!cred_cloned && is_system_labeled()) { + cred_cloned = TRUE; + cr = crdup(icr); + (void) setpflags(NET_MAC_AWARE, 1, cr); + } + /* * clget() calls clnt_tli_kinit() which clears the xid, so we * are guaranteed to reprocess the retry as a new request. @@ -1252,6 +1269,8 @@ failoverretry: * the transfer size changed. */ clfree_impl(client, ch, nfscl); + if (cred_cloned) + crfree(cr); return (ENFS_TRYAGAIN); } } @@ -1348,6 +1367,8 @@ failoverretry: } clfree_impl(client, ch, nfscl); + if (cred_cloned) + crfree(cr); ASSERT(rpcerr.re_status == RPC_SUCCESS || rpcerr.re_errno != 0); @@ -1449,11 +1470,13 @@ acl3call(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, static int aclcall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp, - xdrproc_t xdrres, caddr_t resp, cred_t *cr, int *douprintf, + xdrproc_t xdrres, caddr_t resp, cred_t *icr, int *douprintf, int flags, failinfo_t *fi) { CLIENT *client; struct chtab *ch; + cred_t *cr = icr; + bool_t cred_cloned = FALSE; enum clnt_stat status; struct rpc_err rpcerr; struct timeval wait; @@ -1562,6 +1585,13 @@ failoverretry: } } + /* For TSOL, use a new cred which has net_mac_aware flag */ + if (!cred_cloned && is_system_labeled()) { + cred_cloned = TRUE; + cr = crdup(icr); + (void) setpflags(NET_MAC_AWARE, 1, cr); + } + /* * acl_clget() calls clnt_tli_kinit() which clears the xid, so we * are guaranteed to reprocess the retry as a new request. @@ -1581,8 +1611,11 @@ failoverretry: goto failoverretry; } } - if (rpcerr.re_errno != 0) + if (rpcerr.re_errno != 0) { + if (cred_cloned) + crfree(cr); return (rpcerr.re_errno); + } if (svp->sv_knconf->knc_semantics == NC_TPI_COTS_ORD || svp->sv_knconf->knc_semantics == NC_TPI_COTS) { @@ -1823,6 +1856,8 @@ failoverretry: * the transfer size changed. */ clfree_impl(client, ch, nfscl); + if (cred_cloned) + crfree(cr); return (ENFS_TRYAGAIN); } #endif @@ -1921,6 +1956,8 @@ failoverretry: } clfree_impl(client, ch, nfscl); + if (cred_cloned) + crfree(cr); ASSERT(rpcerr.re_status == RPC_SUCCESS || rpcerr.re_errno != 0); @@ -4972,3 +5009,111 @@ nfs_zoneid(void) { return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid()); } + +/* + * nfs_mount_label_policy: + * Determine whether the mount is allowed according to MAC check, + * by comparing (where appropriate) label of the remote server + * against the label of the zone being mounted into. + * + * Returns: + * 0 : access allowed + * -1 : read-only access allowed (i.e., read-down) + * >0 : error code, such as EACCES + */ +int +nfs_mount_label_policy(vfs_t *vfsp, struct netbuf *addr, + struct knetconfig *knconf, cred_t *cr) +{ + int addr_type; + void *ipaddr; + bslabel_t *server_sl, *mntlabel; + zone_t *mntzone = NULL; + ts_label_t *zlabel; + tsol_tpc_t *tp; + ts_label_t *tsl = NULL; + int retv; + + /* + * Get the zone's label. Each zone on a labeled system has a label. + */ + mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE); + zlabel = mntzone->zone_slabel; + ASSERT(zlabel != NULL); + label_hold(zlabel); + + if (strcmp(knconf->knc_protofmly, NC_INET) == 0) { + addr_type = IPV4_VERSION; + ipaddr = &((struct sockaddr_in *)addr->buf)->sin_addr; + } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) { + addr_type = IPV6_VERSION; + ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr; + } else { + retv = 0; + goto out; + } + + retv = EACCES; /* assume the worst */ + + /* + * Next, get the assigned label of the remote server. + */ + tp = find_tpc(ipaddr, addr_type, B_FALSE); + if (tp == NULL) + goto out; /* error getting host entry */ + + if (tp->tpc_tp.tp_doi != zlabel->tsl_doi) + goto rel_tpc; /* invalid domain */ + if ((tp->tpc_tp.host_type != SUN_CIPSO) && + (tp->tpc_tp.host_type != UNLABELED)) + goto rel_tpc; /* invalid hosttype */ + + if (tp->tpc_tp.host_type == SUN_CIPSO) { + tsl = getflabel_cipso(vfsp); + if (tsl == NULL) + goto rel_tpc; /* error getting server lbl */ + + server_sl = label2bslabel(tsl); + } else { /* UNLABELED */ + server_sl = &tp->tpc_tp.tp_def_label; + } + + mntlabel = label2bslabel(zlabel); + + /* + * Now compare labels to complete the MAC check. If the labels + * are equal or if the requestor is in the global zone and has + * NET_MAC_AWARE, then allow read-write access. (Except for + * mounts into the global zone itself; restrict these to + * read-only.) + * + * If the requestor is in some other zone, but his label + * dominates the server, then allow read-down. + * + * Otherwise, access is denied. + */ + if (blequal(mntlabel, server_sl) || + (crgetzoneid(cr) == GLOBAL_ZONEID && + getpflags(NET_MAC_AWARE, cr) != 0)) { + if ((mntzone == global_zone) || + !blequal(mntlabel, server_sl)) + retv = -1; /* read-only */ + else + retv = 0; /* access OK */ + } else if (bldominates(mntlabel, server_sl)) { + retv = -1; /* read-only */ + } else { + retv = EACCES; + } + + if (tsl != NULL) + label_rele(tsl); + +rel_tpc: + TPC_RELE(tp); +out: + if (mntzone) + zone_rele(mntzone); + label_rele(zlabel); + return (retv); +} |