Skip to content

Instantly share code, notes, and snippets.

@hoxworth
Created April 11, 2013 17:59
Show Gist options
  • Save hoxworth/5365674 to your computer and use it in GitHub Desktop.
Save hoxworth/5365674 to your computer and use it in GitHub Desktop.
Oh the memories...
Index: nfs-2.6/Makefile
diff -u nfs-2.6/Makefile:1.1.1.12 nfs-2.6/Makefile:1.15
--- nfs-2.6/Makefile:1.1.1.12 Wed Mar 2 10:10:24 2005
+++ nfs-2.6/Makefile Wed Mar 2 11:00:18 2005
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 11
-EXTRAVERSION =
+EXTRAVERSION = -selinux1-nfs1
NAME=Woozy Numbat
# *DOCUMENTATION*
Index: nfs-2.6/fs/Kconfig
diff -u nfs-2.6/fs/Kconfig:1.1.1.12 nfs-2.6/fs/Kconfig:1.12
--- nfs-2.6/fs/Kconfig:1.1.1.12 Wed Mar 2 10:21:02 2005
+++ nfs-2.6/fs/Kconfig Wed Mar 2 11:00:41 2005
@@ -1359,6 +1359,24 @@
If unsure, say Y.
+config NFS_XATTR
+ bool "Provide NFSv3 client support for extended attributes"
+ depends on NFS_FS && NFS_V3
+ help
+ Say Y here if you want your NFS client to be able to use extended
+ attributes. This requires the server to be configured as well.
+
+ If unsure, say N
+config NFS_SELINUX
+ bool "Provide NFSv3 client support for SELinux"
+ depends on NFS_FS && NFS_V3 && NFS_XATTR
+ help
+ Say Y here for SELinux support for NFSv3. This requires the
+ SELinux security module on the client, and also that the server
+ is configured to use SELinux for NFSv3 as well.
+
+ If unsure, say N
+
config NFS_V4
bool "Provide NFSv4 client support (EXPERIMENTAL)"
depends on NFS_FS && EXPERIMENTAL
@@ -1432,6 +1450,24 @@
If you would like to include the NFSv3 server as well as the NFSv2
server, say Y here. If unsure, say Y.
+config NFSD_XATTR
+ bool "Provide NFSv3 server support for extended attributes"
+ depends on NFSD && NFSD_V3
+ help
+ Say Y here if you want your NFS server to be able to use extended
+ attributes.
+
+ If unsure, say N
+
+config NFSD_SELINUX
+ bool "Provide NFSv3 server support for SELinux"
+ depends on NFSD && NFSD_V3 && NFSD_XATTR
+ help
+ Say Y here for SELinux support for NFSV3. This requires the
+ SELinux security module as well.
+
+ If unsure, say N
+
config NFSD_V4
bool "Provide NFSv4 server support (EXPERIMENTAL)"
depends on NFSD_V3 && EXPERIMENTAL
Index: nfs-2.6/fs/lockd/svc.c
diff -u nfs-2.6/fs/lockd/svc.c:1.1.1.6 nfs-2.6/fs/lockd/svc.c:1.13
--- nfs-2.6/fs/lockd/svc.c:1.1.1.6 Wed Mar 2 10:22:22 2005
+++ nfs-2.6/fs/lockd/svc.c Wed Mar 16 13:17:01 2005
@@ -477,6 +477,7 @@
#define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
static struct svc_program nlmsvc_program = {
+ .pg_next = NULL, /* last registered program */
.pg_prog = NLM_PROGRAM, /* program number */
.pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
.pg_vers = nlmsvc_version, /* version table */
Index: nfs-2.6/fs/nfs/Makefile
diff -u nfs-2.6/fs/nfs/Makefile:1.1.1.2 nfs-2.6/fs/nfs/Makefile:1.5
--- nfs-2.6/fs/nfs/Makefile:1.1.1.2 Thu Oct 21 12:02:33 2004
+++ nfs-2.6/fs/nfs/Makefile Fri Oct 22 16:27:14 2004
@@ -6,6 +6,8 @@
nfs-y := dir.o file.o inode.o nfs2xdr.o pagelist.o \
proc.o read.o symlink.o unlink.o write.o
+
+nfs-$(CONFIG_NFS_XATTR) += xattr.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
Index: nfs-2.6/fs/nfs/dir.c
diff -u nfs-2.6/fs/nfs/dir.c:1.1.1.7 nfs-2.6/fs/nfs/dir.c:1.13
--- nfs-2.6/fs/nfs/dir.c:1.1.1.7 Wed Mar 2 10:21:25 2005
+++ nfs-2.6/fs/nfs/dir.c Wed Mar 2 11:00:42 2005
@@ -31,6 +31,7 @@
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include <linux/sunrpc/xattr.h>
#include "delegation.h"
@@ -72,6 +73,10 @@
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+#ifdef CONFIG_NFS_XATTR
+ .getxattr = nfs_getxattr,
+ .setxattr = nfs_setxattr,
+#endif
};
#ifdef CONFIG_NFS_V4
@@ -1498,13 +1503,14 @@
int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct rpc_cred *cred;
+ struct rpc_clnt *client = NFS_CLIENT(inode);
int res;
if (mask == 0)
return 0;
/* Are we checking permissions on anything other than lookup/execute? */
- if ((mask & MAY_EXEC) == 0) {
+ if (!client->cl_selinux && ((mask & MAY_EXEC) == 0)) {
/* We only need to check permissions on file open() and access() */
if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
return 0;
Index: nfs-2.6/fs/nfs/file.c
diff -u nfs-2.6/fs/nfs/file.c:1.1.1.9 nfs-2.6/fs/nfs/file.c:1.12
--- nfs-2.6/fs/nfs/file.c:1.1.1.9 Wed Mar 2 10:21:29 2005
+++ nfs-2.6/fs/nfs/file.c Wed Mar 2 11:00:42 2005
@@ -30,6 +30,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <linux/sunrpc/xattr.h>
#include "delegation.h"
@@ -65,6 +66,10 @@
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+#ifdef CONFIG_NFS_XATTR
+ .getxattr = nfs_getxattr,
+ .setxattr = nfs_setxattr,
+#endif
};
/* Hack for future NFS swap support */
Index: nfs-2.6/fs/nfs/inode.c
diff -u nfs-2.6/fs/nfs/inode.c:1.1.1.10 nfs-2.6/fs/nfs/inode.c:1.27
--- nfs-2.6/fs/nfs/inode.c:1.1.1.10 Wed Mar 2 10:21:27 2005
+++ nfs-2.6/fs/nfs/inode.c Wed Mar 30 12:41:41 2005
@@ -35,6 +35,8 @@
#include <linux/mount.h>
#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
+#include <linux/sunrpc/selinux.h>
+#include <linux/sunrpc/xattr.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -104,6 +106,54 @@
.pipe_dir_name = "/nfs",
};
+#ifdef CONFIG_NFS_SELINUX
+/* RPC cruft for selinuxnfs */
+struct rpc_stat selinux_nfs_rpcstat = {
+ .program = &selinux_nfs_program
+};
+
+static struct rpc_version * selinux_nfs_version[] = {
+ NULL,
+ NULL,
+ NULL,
+ &selinux_nfs_version3,
+};
+
+struct rpc_program selinux_nfs_program = {
+ .name = "selinuxnfs",
+ .number = SELINUX_NFS_PROGRAM,
+ .nrvers = sizeof(selinux_nfs_version) /
+ sizeof(selinux_nfs_version[0]),
+ .version = selinux_nfs_version,
+ .stats = &selinux_nfs_rpcstat,
+ .pipe_dir_name = "/selinuxnfs",
+};
+#endif /* CONFIG_NFS_SELINUX */
+
+#ifdef CONFIG_NFS_XATTR
+/* RPC cruft for xattrnfs */
+struct rpc_stat xattr_nfs_rpcstat = {
+ .program = &xattr_nfs_program
+};
+
+static struct rpc_version * xattr_nfs_version[] = {
+ NULL,
+ NULL,
+ NULL,
+ &xattr_nfs_version3,
+};
+
+struct rpc_program xattr_nfs_program = {
+ .name = "xattrnfs",
+ .number = XATTR_NFS_PROGRAM,
+ .nrvers = sizeof(xattr_nfs_version) /
+ sizeof(xattr_nfs_version[0]),
+ .version = xattr_nfs_version,
+ .stats = &xattr_nfs_rpcstat,
+ .pipe_dir_name = "/xattrnfs",
+};
+#endif /* CONFIG_NFS_XATTR */
+
static inline unsigned long
nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
{
@@ -337,6 +387,7 @@
struct rpc_timeout timeparms;
struct rpc_xprt *xprt = NULL;
struct rpc_clnt *clnt = NULL;
+ struct rpc_program *program;
int tcp = (data->flags & NFS_MOUNT_TCP);
/* Initialize timeout values */
@@ -357,7 +408,18 @@
printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
return (struct rpc_clnt *)xprt;
}
- clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+
+ program = &nfs_program;
+#ifdef CONFIG_NFS_XATTR
+ if (data->flags & NFS_MOUNT_XATTR)
+ program = &xattr_nfs_program;
+#endif
+#ifdef CONFIG_NFS_SELINUX
+ if (data->flags & NFS_MOUNT_SELINUX)
+ program = &selinux_nfs_program;
+#endif
+
+ clnt = rpc_create_client(xprt, server->hostname, program,
server->rpc_ops->version, data->pseudoflavor);
if (IS_ERR(clnt)) {
printk(KERN_WARNING "NFS: cannot create RPC client.\n");
@@ -368,6 +430,11 @@
clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
clnt->cl_chatty = 1;
+#ifdef CONFIG_NFS_SELINUX
+ clnt->cl_selinux = (server->flags & NFS_MOUNT_SELINUX) ? 1 : 0;
+#else
+ clnt->cl_selinux = 0;
+#endif
return clnt;
@@ -419,6 +486,19 @@
if (server->flags & NFS_MOUNT_VER3) {
#ifdef CONFIG_NFS_V3
server->rpc_ops = &nfs_v3_clientops;
+ if (data->flags & NFS_MOUNT_XATTR)
+#ifdef CONFIG_NFS_XATTR
+ server->rpc_ops = &nfs_v3ea_clientops;
+#else
+ printk(KERN_NOTICE "NFS: NFSv3 extended attributes not supported.\n");
+#endif
+ if (data->flags & NFS_MOUNT_SELINUX)
+#ifdef CONFIG_NFS_SELINUX
+ server->rpc_ops = &nfs_v3se_clientops;
+#else
+ printk(KERN_NOTICE "NFS: NFSv3 with selinux not supported.\n");
+#endif
+
server->caps |= NFS_CAP_READDIRPLUS;
if (data->version < 4) {
printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
@@ -534,6 +614,8 @@
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
{ NFS_MOUNT_INTR, ",intr", "" },
{ NFS_MOUNT_POSIX, ",posix", "" },
+ { NFS_MOUNT_XATTR, ",xattr", "" },
+ { NFS_MOUNT_SELINUX, ",selinux", "" },
{ NFS_MOUNT_TCP, ",tcp", ",udp" },
{ NFS_MOUNT_NOCTO, ",nocto", "" },
{ NFS_MOUNT_NOAC, ",noac", "" },
@@ -968,7 +1050,8 @@
goto out_nowait;
if (NFS_ATTRTIMEO(inode) == 0)
continue;
- if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))
+ if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|
+ NFS_INO_INVALID_ATIME|NFS_INO_INVALID_XATTR))
continue;
status = NFS_STALE(inode) ? -ESTALE : 0;
goto out_nowait;
@@ -1024,6 +1107,17 @@
inode->i_sb->s_id,
(long long)NFS_FILEID(inode));
+#ifdef CONFIG_NFS_SELINUX
+ if ((NFS_PROTO(inode)->getxattr) &&
+ (nfsi->flags & NFS_INO_INVALID_XATTR)) {
+ status = security_revalidate_inode(inode);
+ if (status) {
+ dfprintk(PAGECACHE, "security_revalidate_inode: (%s/%Ld) failed, error=%d\n",
+ inode->i_sb->s_id, (long long)NFS_FILEID(inode), status);
+ }
+ nfsi->flags &= ~NFS_INO_INVALID_XATTR;
+ }
+#endif
out:
NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
wake_up(&nfsi->nfs_i_wait);
@@ -1050,7 +1144,8 @@
*/
int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
- if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+ if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|
+ NFS_INO_INVALID_XATTR))
&& !nfs_attribute_timeout(inode))
return NFS_STALE(inode) ? -ESTALE : 0;
return __nfs_revalidate_inode(server, inode);
@@ -1139,7 +1234,7 @@
nfsi->flags |= NFS_INO_INVALID_ATTR;
}
- if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+ if ((fattr->valid & (NFS_ATTR_FATTR | NFS_XATTR_FATTR)) == 0)
return 0;
/* Has the inode gone and changed behind our back? */
@@ -1179,6 +1274,12 @@
if (!timespec_equal(&inode->i_atime, &fattr->atime))
nfsi->flags |= NFS_INO_INVALID_ATIME;
+#ifdef CONFIG_NFS_SELINUX
+ /* Has the security context changed? */
+ if ((fattr->valid & NFS_XATTR_FATTR) && (nfsi->sid != fattr->sid))
+ nfsi->flags |= (NFS_INO_INVALID_XATTR | NFS_INO_INVALID_ACCESS);
+#endif
+
nfsi->read_cache_jiffies = fattr->timestamp;
return 0;
}
@@ -1322,6 +1423,13 @@
if (!nfs_have_delegation(inode, FMODE_READ))
nfsi->flags |= invalid;
+#ifdef CONFIG_NFS_SELINUX
+ /* Save security id from the server */
+ if ((fattr->valid & NFS_XATTR_FATTR) && (nfsi->sid != fattr->sid)) {
+ nfsi->flags |= (NFS_INO_INVALID_XATTR | NFS_INO_INVALID_ACCESS);
+ nfsi->sid = fattr->sid;
+ }
+#endif
return 0;
out_changed:
/*
@@ -1929,6 +2037,12 @@
#ifdef CONFIG_PROC_FS
rpc_proc_register(&nfs_rpcstat);
+#ifdef CONFIG_NFS_SELINUX
+ rpc_proc_register(&selinux_nfs_rpcstat);
+#endif
+#ifdef CONFIG_NFS_XATTR
+ rpc_proc_register(&xattr_nfs_rpcstat);
+#endif
#endif
err = register_filesystem(&nfs_fs_type);
if (err)
@@ -1940,6 +2054,12 @@
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
+#ifdef CONFIG_NFS_SELINUX
+ rpc_proc_unregister("selinuxnfs");
+#endif
+#ifdef CONFIG_NFS_XATTR
+ rpc_proc_unregister("xattrnfs");
+#endif
nfs_destroy_writepagecache();
#ifdef CONFIG_NFS_DIRECTIO
out0:
@@ -1966,6 +2086,12 @@
nfs_destroy_nfspagecache();
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
+#ifdef CONFIG_NFS_SELINUX
+ rpc_proc_unregister("selinuxnfs");
+#endif
+#ifdef CONFIG_NFS_XATTR
+ rpc_proc_unregister("xattrnfs");
+#endif
#endif
unregister_filesystem(&nfs_fs_type);
unregister_nfs4fs();
Index: nfs-2.6/fs/nfs/nfs2xdr.c
diff -u nfs-2.6/fs/nfs/nfs2xdr.c:1.1.1.7 nfs-2.6/fs/nfs/nfs2xdr.c:1.7
--- nfs-2.6/fs/nfs/nfs2xdr.c:1.1.1.7 Thu Oct 21 12:02:32 2004
+++ nfs-2.6/fs/nfs/nfs2xdr.c Fri Oct 22 16:27:14 2004
@@ -638,6 +638,10 @@
{ NFSERR_NOSPC, ENOSPC },
{ NFSERR_ROFS, EROFS },
{ NFSERR_MLINK, EMLINK },
+#ifdef CONFIG_NFSD_XATTR
+ { NFSERR_ERANGE, ERANGE },
+ { NFSERR_EOPNOTSUPP, EOPNOTSUPP },
+#endif
{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
{ NFSERR_NOTEMPTY, ENOTEMPTY },
{ NFSERR_DQUOT, EDQUOT },
Index: nfs-2.6/fs/nfs/nfs3proc.c
diff -u nfs-2.6/fs/nfs/nfs3proc.c:1.1.1.7 nfs-2.6/fs/nfs/nfs3proc.c:1.14
--- nfs-2.6/fs/nfs/nfs3proc.c:1.1.1.7 Wed Mar 2 10:21:26 2005
+++ nfs-2.6/fs/nfs/nfs3proc.c Wed Mar 30 09:51:35 2005
@@ -17,11 +17,11 @@
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include <linux/smp_lock.h>
+#include <linux/limits.h>
+#include <linux/sunrpc/xattr.h>
#define NFSDBG_FACILITY NFSDBG_PROC
-extern struct rpc_procinfo nfs3_procedures[];
-
/* A wrapper to handle the EJUKEBOX error message */
static int
nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
@@ -45,7 +45,7 @@
nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
{
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[proc],
+ .rpc_proc = &clnt->cl_procinfo[proc],
.rpc_argp = argp,
.rpc_resp = resp,
};
@@ -155,6 +155,7 @@
static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
+ struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_fattr fattr;
struct nfs3_accessargs arg = {
.fh = NFS_FH(inode),
@@ -163,7 +164,7 @@
.fattr = &fattr,
};
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_ACCESS],
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = entry->cred
@@ -187,7 +188,7 @@
if (mode & MAY_EXEC)
arg.access |= NFS3_ACCESS_EXECUTE;
}
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = rpc_call_sync(clnt, &msg, 0);
nfs_refresh_inode(inode, &fattr);
if (status == 0) {
entry->mask = 0;
@@ -227,9 +228,10 @@
{
int flags = rdata->flags;
struct inode * inode = rdata->inode;
+ struct rpc_clnt * clnt = NFS_CLIENT(inode);
struct nfs_fattr * fattr = rdata->res.fattr;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READ],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_READ],
.rpc_argp = &rdata->args,
.rpc_resp = &rdata->res,
.rpc_cred = rdata->cred,
@@ -239,7 +241,7 @@
dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
(long long) rdata->args.offset);
fattr->valid = 0;
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
+ status = rpc_call_sync(clnt, &msg, flags);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
dprintk("NFS reply read: %d\n", status);
@@ -250,9 +252,10 @@
{
int rpcflags = wdata->flags;
struct inode * inode = wdata->inode;
+ struct rpc_clnt * clnt = NFS_CLIENT(inode);
struct nfs_fattr * fattr = wdata->res.fattr;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_WRITE],
.rpc_argp = &wdata->args,
.rpc_resp = &wdata->res,
.rpc_cred = wdata->cred,
@@ -262,7 +265,7 @@
dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
(long long) wdata->args.offset);
fattr->valid = 0;
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
+ status = rpc_call_sync(clnt, &msg, rpcflags);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
dprintk("NFS reply write: %d\n", status);
@@ -272,9 +275,10 @@
static int nfs3_proc_commit(struct nfs_write_data *cdata)
{
struct inode * inode = cdata->inode;
+ struct rpc_clnt * clnt = NFS_CLIENT(inode);
struct nfs_fattr * fattr = cdata->res.fattr;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_COMMIT],
.rpc_argp = &cdata->args,
.rpc_resp = &cdata->res,
.rpc_cred = cdata->cred,
@@ -284,7 +288,7 @@
dprintk("NFS call commit %d @ %Ld\n", cdata->args.count,
(long long) cdata->args.offset);
fattr->valid = 0;
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = rpc_call_sync(clnt, &msg, 0);
if (status >= 0)
nfs_refresh_inode(inode, fattr);
dprintk("NFS reply commit: %d\n", status);
@@ -394,6 +398,7 @@
static int
nfs3_proc_remove(struct inode *dir, struct qstr *name)
{
+ struct rpc_clnt * clnt = NFS_CLIENT(dir);
struct nfs_fattr dir_attr;
struct nfs3_diropargs arg = {
.fh = NFS_FH(dir),
@@ -401,7 +406,7 @@
.len = name->len
};
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_REMOVE],
.rpc_argp = &arg,
.rpc_resp = &dir_attr,
};
@@ -409,7 +414,7 @@
dprintk("NFS call remove %s\n", name->name);
dir_attr.valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call_sync(clnt, &msg, 0);
nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply remove: %d\n", status);
return status;
@@ -418,6 +423,8 @@
static int
nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
{
+ struct inode * inode = dir->d_inode;
+ struct rpc_clnt * clnt = NFS_CLIENT(inode);
struct unlinkxdr {
struct nfs3_diropargs arg;
struct nfs_fattr res;
@@ -426,11 +433,11 @@
ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
- ptr->arg.fh = NFS_FH(dir->d_inode);
+ ptr->arg.fh = NFS_FH(inode);
ptr->arg.name = name->name;
ptr->arg.len = name->len;
ptr->res.valid = 0;
- msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
+ msg->rpc_proc = &clnt->cl_procinfo[NFS3PROC_REMOVE];
msg->rpc_argp = &ptr->arg;
msg->rpc_resp = &ptr->res;
return 0;
@@ -599,6 +606,7 @@
u64 cookie, struct page *page, unsigned int count, int plus)
{
struct inode *dir = dentry->d_inode;
+ struct rpc_clnt *clnt = NFS_CLIENT(dir);
struct nfs_fattr dir_attr;
u32 *verf = NFS_COOKIEVERF(dir);
struct nfs3_readdirargs arg = {
@@ -615,7 +623,7 @@
.plus = plus
};
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_READDIR],
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = cred
@@ -625,13 +633,13 @@
lock_kernel();
if (plus)
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
+ msg.rpc_proc = &clnt->cl_procinfo[NFS3PROC_READDIRPLUS];
dprintk("NFS call readdir%s %d\n",
plus? "plus" : "", (unsigned int) cookie);
dir_attr.valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = rpc_call_sync(clnt, &msg, 0);
nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply readdir: %d\n", status);
unlock_kernel();
@@ -734,9 +742,10 @@
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
+ struct rpc_clnt *clnt = NFS_CLIENT(inode);
int flags;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READ],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_READ],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
@@ -746,7 +755,7 @@
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags);
+ rpc_init_task(task, clnt, nfs3_read_done, flags);
rpc_call_setup(task, &msg, 0);
}
@@ -768,10 +777,11 @@
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
+ struct rpc_clnt *clnt = NFS_CLIENT(inode);
int stable;
int flags;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_WRITE],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
@@ -790,7 +800,7 @@
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags);
+ rpc_init_task(task, clnt, nfs3_write_done, flags);
rpc_call_setup(task, &msg, 0);
}
@@ -812,9 +822,10 @@
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
+ struct rpc_clnt *clnt = NFS_CLIENT(inode);
int flags;
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
+ .rpc_proc = &clnt->cl_procinfo[NFS3PROC_COMMIT],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
@@ -824,7 +835,7 @@
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags);
+ rpc_init_task(task, clnt, nfs3_commit_done, flags);
rpc_call_setup(task, &msg, 0);
}
@@ -834,6 +845,50 @@
return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
}
+#ifdef CONFIG_NFS_XATTR
+static int
+nfs3_proc_getxattr(struct dentry *dentry, const char *name, void *buffer,
+ unsigned int size, unsigned int *xattrlen)
+{
+ struct inode *inode = dentry->d_inode;
+ struct nfs3_getxattrargs arg = {
+ .fh = NFS_FH(inode),
+ .name = name,
+ .namelen = strnlen(name, XATTR_NAME_MAX+1),
+ .bufsize = size,
+ };
+ struct nfs3_getxattrres res = {
+ .buffer = buffer,
+ .xattrlen = xattrlen,
+ .sid = &NFS_I(inode)->sid,
+ };
+ if (arg.namelen > XATTR_NAME_MAX)
+ return -ERANGE;
+ return rpc_call(NFS_CLIENT(inode), NFS3PROC_GETXATTR, &arg, &res, 0);
+}
+
+static int
+nfs3_proc_setxattr(struct dentry *dentry, const char *name, const void *value,
+ unsigned int size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ struct nfs3_setxattrargs arg = {
+ .fh = NFS_FH(inode),
+ .name = name,
+ .namelen = strnlen(name, XATTR_NAME_MAX+1),
+ .value = value,
+ .size = size,
+ .flags = flags,
+ };
+ struct nfs3_setxattrres res = {
+ .sid = &NFS_I(inode)->sid,
+ };
+ if (arg.namelen > XATTR_NAME_MAX)
+ return -ERANGE;
+ return rpc_call(NFS_CLIENT(inode), NFS3PROC_SETXATTR, &arg, &res, 0);
+}
+#endif /* CONFIG_NFS_XATTR */
+
struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
@@ -869,3 +924,87 @@
.file_release = nfs_release,
.lock = nfs3_proc_lock,
};
+
+#ifdef CONFIG_NFS_XATTR
+struct nfs_rpc_ops nfs_v3ea_clientops = {
+ .version = 3, /* protocol version */
+ .dentry_ops = &nfs_dentry_operations,
+ .dir_inode_ops = &nfs_dir_inode_operations,
+ .getroot = nfs3_proc_get_root,
+ .getattr = nfs3_proc_getattr,
+ .setattr = nfs3_proc_setattr,
+ .lookup = nfs3_proc_lookup,
+ .access = nfs3_proc_access,
+ .readlink = nfs3_proc_readlink,
+ .read = nfs3_proc_read,
+ .write = nfs3_proc_write,
+ .commit = nfs3_proc_commit,
+ .create = nfs3_proc_create,
+ .remove = nfs3_proc_remove,
+ .unlink_setup = nfs3_proc_unlink_setup,
+ .unlink_done = nfs3_proc_unlink_done,
+ .rename = nfs3_proc_rename,
+ .link = nfs3_proc_link,
+ .symlink = nfs3_proc_symlink,
+ .mkdir = nfs3_proc_mkdir,
+ .rmdir = nfs3_proc_rmdir,
+ .readdir = nfs3_proc_readdir,
+ .mknod = nfs3_proc_mknod,
+ .statfs = nfs3_proc_statfs,
+ .fsinfo = nfs3_proc_fsinfo,
+ .pathconf = nfs3_proc_pathconf,
+ .decode_dirent = nfs3_decode_dirent,
+ .read_setup = nfs3_proc_read_setup,
+ .write_setup = nfs3_proc_write_setup,
+ .commit_setup = nfs3_proc_commit_setup,
+ .file_open = nfs_open,
+ .file_release = nfs_release,
+ .lock = nfs3_proc_lock,
+ .getxattr = nfs3_proc_getxattr,
+ .setxattr = nfs3_proc_setxattr,
+};
+#else
+#define nfs_v3ea_clientops nfs_v3_clientops
+#endif /* CONFIG_NFS_XATTR */
+
+#ifdef CONFIG_NFS_SELINUX
+struct nfs_rpc_ops nfs_v3se_clientops = {
+ .version = 3, /* protocol version */
+ .dentry_ops = &nfs_dentry_operations,
+ .dir_inode_ops = &nfs_dir_inode_operations,
+ .getroot = nfs3_proc_get_root,
+ .getattr = nfs3_proc_getattr,
+ .setattr = nfs3_proc_setattr,
+ .lookup = nfs3_proc_lookup,
+ .access = nfs3_proc_access,
+ .readlink = nfs3_proc_readlink,
+ .read = nfs3_proc_read,
+ .write = nfs3_proc_write,
+ .commit = nfs3_proc_commit,
+ .create = nfs3_proc_create,
+ .remove = nfs3_proc_remove,
+ .unlink_setup = nfs3_proc_unlink_setup,
+ .unlink_done = nfs3_proc_unlink_done,
+ .rename = nfs3_proc_rename,
+ .link = nfs3_proc_link,
+ .symlink = nfs3_proc_symlink,
+ .mkdir = nfs3_proc_mkdir,
+ .rmdir = nfs3_proc_rmdir,
+ .readdir = nfs3_proc_readdir,
+ .mknod = nfs3_proc_mknod,
+ .statfs = nfs3_proc_statfs,
+ .fsinfo = nfs3_proc_fsinfo,
+ .pathconf = nfs3_proc_pathconf,
+ .decode_dirent = nfs3_decode_dirent,
+ .read_setup = nfs3_proc_read_setup,
+ .write_setup = nfs3_proc_write_setup,
+ .commit_setup = nfs3_proc_commit_setup,
+ .file_open = nfs_open,
+ .file_release = nfs_release,
+ .lock = nfs3_proc_lock,
+ .getxattr = nfs3_proc_getxattr,
+ .setxattr = nfs3_proc_setxattr,
+};
+#else
+#define nfs_v3se_clientops nfs_v3_clientops
+#endif /* CONFIG_NFS_SELINUX */
Index: nfs-2.6/fs/nfs/nfs3xdr.c
diff -u nfs-2.6/fs/nfs/nfs3xdr.c:1.1.1.7 nfs-2.6/fs/nfs/nfs3xdr.c:1.21
--- nfs-2.6/fs/nfs/nfs3xdr.c:1.1.1.7 Thu Oct 21 12:02:32 2004
+++ nfs-2.6/fs/nfs/nfs3xdr.c Wed Mar 30 09:51:35 2005
@@ -21,6 +21,8 @@
#include <linux/nfs.h>
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
+#include <linux/limits.h> /* for XATTR_NAME_MAX */
+#include <linux/sunrpc/xattr.h>
#define NFSDBG_FACILITY NFSDBG_XDR
@@ -33,12 +35,14 @@
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
*/
+#define NFS3_xattr_name_sz (1+XDR_QUADLEN(XATTR_NAME_MAX))
+#define NFS3_xattr_value_sz (1+XDR_QUADLEN(NFS_XATTR_SIZE_MAX))
#define NFS3_fhandle_sz (1+16)
#define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
#define NFS3_sattr_sz (15)
#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
-#define NFS3_fattr_sz (21)
+#define NFS3_fattr_sz (21 + 1) /* + 1 for SELinux sid */
#define NFS3_wcc_attr_sz (6)
#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
@@ -62,6 +66,8 @@
#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
#define NFS3_readdirargs_sz (NFS3_fh_sz+2)
#define NFS3_commitargs_sz (NFS3_fh_sz+3)
+#define NFS3_getxattrargs_sz (NFS3_fh_sz+NFS3_xattr_name_sz+1)
+#define NFS3_setxattrargs_sz (NFS3_fh_sz+NFS3_xattr_name_sz+NFS3_xattr_value_sz+1)
#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
@@ -78,6 +84,8 @@
#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
+#define NFS3_getxattrres_sz (1+1+NFS3_xattr_value_sz+1)
+#define NFS3_setxattrres_sz (1+1)
/*
* Map file type to S_IFMT bits
@@ -229,10 +237,26 @@
}
static inline u32 *
-xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
+_xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
{
if (*p++)
p = xdr_decode_fattr(p, fattr);
+
+ return p;
+}
+
+static inline u32 *
+xdr_decode_post_op_attr(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+{
+ if (*p++) {
+ p = xdr_decode_fattr(p, fattr);
+#ifdef CONFIG_NFS_SELINUX
+ if (req->rq_task->tk_client->cl_selinux) {
+ fattr->sid = ntohl(*p++);
+ fattr->valid |= NFS_XATTR_FATTR;
+ }
+#endif
+ }
return p;
}
@@ -246,10 +270,10 @@
static inline u32 *
-xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
+xdr_decode_wcc_data(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
{
p = xdr_decode_pre_op_attr(p, fattr);
- return xdr_decode_post_op_attr(p, fattr);
+ return xdr_decode_post_op_attr(req, p, fattr);
}
/*
@@ -489,7 +513,7 @@
status = ntohl(*p++);
/* Decode post_op_attrs */
- p = xdr_decode_post_op_attr(p, res->dir_attr);
+ p = xdr_decode_post_op_attr(req, p, res->dir_attr);
if (status)
return -nfs_stat_to_errno(status);
/* Decode verifier cookie */
@@ -596,7 +620,7 @@
if (plus) {
entry->fattr->valid = 0;
- p = xdr_decode_post_op_attr(p, entry->fattr);
+ p = _xdr_decode_post_op_attr(p, entry->fattr);
/* In fact, a post_op_fh3: */
if (*p++) {
p = xdr_decode_fhandle(p, entry->fh);
@@ -627,6 +651,37 @@
return 0;
}
+#ifdef CONFIG_NFS_XATTR
+/*
+ * Encode GETXATTR request
+ */
+static int
+nfs3_xdr_getxattrargs(struct rpc_rqst *req, u32 *p,
+ struct nfs3_getxattrargs *args)
+{
+ p = xdr_encode_fhandle(p, args->fh);
+ p = xdr_encode_array(p, args->name, args->namelen+1);
+ *p++ = htonl(args->bufsize);
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+ return 0;
+}
+
+/*
+ * Encode SETXATTR request
+ */
+static int
+nfs3_xdr_setxattrargs(struct rpc_rqst *req, u32 *p,
+ struct nfs3_setxattrargs *args)
+{
+ p = xdr_encode_fhandle(p, args->fh);
+ p = xdr_encode_array(p, args->name, args->namelen+1);
+ p = xdr_encode_array(p, args->value, args->size);
+ *p++ = htonl(args->flags);
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+ return 0;
+}
+#endif /* CONFIG_NFS_XATTR */
+
/*
* NFS XDR decode functions
*/
@@ -641,7 +696,13 @@
if ((status = ntohl(*p++)))
return -nfs_stat_to_errno(status);
- xdr_decode_fattr(p, fattr);
+ p = xdr_decode_fattr(p, fattr);
+#ifdef CONFIG_NFS_SELINUX
+ if (req->rq_task->tk_client->cl_selinux) {
+ fattr->sid = ntohl(*p++);
+ fattr->valid |= NFS_XATTR_FATTR;
+ }
+#endif
return 0;
}
@@ -656,7 +717,7 @@
if ((status = ntohl(*p++)))
status = -nfs_stat_to_errno(status);
- xdr_decode_wcc_data(p, fattr);
+ xdr_decode_wcc_data(req, p, fattr);
return status;
}
@@ -673,9 +734,9 @@
} else {
if (!(p = xdr_decode_fhandle(p, res->fh)))
return -errno_NFSERR_IO;
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
}
- xdr_decode_post_op_attr(p, res->dir_attr);
+ xdr_decode_post_op_attr(req, p, res->dir_attr);
return status;
}
@@ -687,7 +748,7 @@
{
int status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
if (status)
return -nfs_stat_to_errno(status);
res->access = ntohl(*p++);
@@ -722,7 +783,7 @@
int status;
status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, fattr);
+ p = xdr_decode_post_op_attr(req, p, fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -767,7 +828,7 @@
int status, count, ocount, recvd, hdrlen;
status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -817,7 +878,7 @@
int status;
status = ntohl(*p++);
- p = xdr_decode_wcc_data(p, res->fattr);
+ p = xdr_decode_wcc_data(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -843,17 +904,17 @@
if (*p++) {
if (!(p = xdr_decode_fhandle(p, res->fh)))
return -errno_NFSERR_IO;
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
} else {
memset(res->fh, 0, sizeof(*res->fh));
/* Do decode post_op_attr but set it to NULL */
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
res->fattr->valid = 0;
}
} else {
status = -nfs_stat_to_errno(status);
}
- p = xdr_decode_wcc_data(p, res->dir_attr);
+ p = xdr_decode_wcc_data(req, p, res->dir_attr);
return status;
}
@@ -867,8 +928,8 @@
if ((status = ntohl(*p++)) != 0)
status = -nfs_stat_to_errno(status);
- p = xdr_decode_wcc_data(p, res->fromattr);
- p = xdr_decode_wcc_data(p, res->toattr);
+ p = xdr_decode_wcc_data(req, p, res->fromattr);
+ p = xdr_decode_wcc_data(req, p, res->toattr);
return status;
}
@@ -882,8 +943,8 @@
if ((status = ntohl(*p++)) != 0)
status = -nfs_stat_to_errno(status);
- p = xdr_decode_post_op_attr(p, res->fattr);
- p = xdr_decode_wcc_data(p, res->dir_attr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
+ p = xdr_decode_wcc_data(req, p, res->dir_attr);
return status;
}
@@ -897,7 +958,7 @@
status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -922,7 +983,7 @@
status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -950,7 +1011,7 @@
status = ntohl(*p++);
- p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_post_op_attr(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
res->max_link = ntohl(*p++);
@@ -969,7 +1030,7 @@
int status;
status = ntohl(*p++);
- p = xdr_decode_wcc_data(p, res->fattr);
+ p = xdr_decode_wcc_data(req, p, res->fattr);
if (status != 0)
return -nfs_stat_to_errno(status);
@@ -978,6 +1039,52 @@
return 0;
}
+#ifdef CONFIG_NFS_XATTR
+/*
+ * Decode GETXATTR result
+ */
+static int
+nfs3_xdr_getxattrres(struct rpc_rqst *req, u32 *p, struct nfs3_getxattrres *res)
+{
+ int status;
+ int len;
+
+ status = ntohl(*p++);
+ if (status != 0)
+ return -nfs_stat_to_errno(status);
+
+ *res->xattrlen = ntohl(*p++);
+ len = ntohl(*p++);
+ if (len) {
+ memcpy(res->buffer,p,len);
+ p += XDR_QUADLEN(len);
+ }
+#ifdef CONFIG_NFS_SELINUX
+ if ((req->rq_task->tk_client->cl_selinux) && *p)
+ *res->sid = ntohl(*p++);
+#endif
+ return 0;
+}
+
+/*
+ * Decode SETXATTR result
+ */
+static int
+nfs3_xdr_setxattrres(struct rpc_rqst *req, u32 *p, struct nfs3_setxattrres *res)
+{
+ int status;
+
+ status = ntohl(*p++);
+ if (status != 0)
+ return -nfs_stat_to_errno(status);
+#ifdef CONFIG_NFS_SELINUX
+ if ((req->rq_task->tk_client->cl_selinux) && *p)
+ *res->sid = ntohl(*p++);
+#endif
+ return 0;
+}
+#endif /* CONFIG_NFS_XATTR */
+
#ifndef MAX
# define MAX(a, b) (((a) > (b))? (a) : (b))
#endif
@@ -1021,3 +1128,72 @@
.procs = nfs3_procedures
};
+#ifdef CONFIG_NFS_XATTR
+struct rpc_procinfo xattr_nfs3_procedures[] = {
+ PROC(GETATTR, fhandle, attrstat, 1),
+ PROC(SETATTR, sattrargs, wccstat, 0),
+ PROC(LOOKUP, diropargs, lookupres, 2),
+ PROC(ACCESS, accessargs, accessres, 1),
+ PROC(READLINK, readlinkargs, readlinkres, 3),
+ PROC(READ, readargs, readres, 3),
+ PROC(WRITE, writeargs, writeres, 4),
+ PROC(CREATE, createargs, createres, 0),
+ PROC(MKDIR, mkdirargs, createres, 0),
+ PROC(SYMLINK, symlinkargs, createres, 0),
+ PROC(MKNOD, mknodargs, createres, 0),
+ PROC(REMOVE, diropargs, wccstat, 0),
+ PROC(RMDIR, diropargs, wccstat, 0),
+ PROC(RENAME, renameargs, renameres, 0),
+ PROC(LINK, linkargs, linkres, 0),
+ PROC(READDIR, readdirargs, readdirres, 3),
+ PROC(READDIRPLUS, readdirargs, readdirres, 3),
+ PROC(FSSTAT, fhandle, fsstatres, 0),
+ PROC(FSINFO, fhandle, fsinfores, 0),
+ PROC(PATHCONF, fhandle, pathconfres, 0),
+ PROC(COMMIT, commitargs, commitres, 5),
+ PROC(GETXATTR, getxattrargs, getxattrres, 1),
+ PROC(SETXATTR, setxattrargs, setxattrres, 0),
+};
+
+struct rpc_version xattr_nfs_version3 = {
+ .number = 3,
+ .nrprocs = sizeof(xattr_nfs3_procedures)/
+ sizeof(xattr_nfs3_procedures[0]),
+ .procs = xattr_nfs3_procedures
+};
+#endif /* CONFIG_NFS_XATTR */
+
+#ifdef CONFIG_NFS_SELINUX
+struct rpc_procinfo selinux_nfs3_procedures[] = {
+ PROC(GETATTR, fhandle, attrstat, 1),
+ PROC(SETATTR, sattrargs, wccstat, 0),
+ PROC(LOOKUP, diropargs, lookupres, 2),
+ PROC(ACCESS, accessargs, accessres, 1),
+ PROC(READLINK, readlinkargs, readlinkres, 3),
+ PROC(READ, readargs, readres, 3),
+ PROC(WRITE, writeargs, writeres, 4),
+ PROC(CREATE, createargs, createres, 0),
+ PROC(MKDIR, mkdirargs, createres, 0),
+ PROC(SYMLINK, symlinkargs, createres, 0),
+ PROC(MKNOD, mknodargs, createres, 0),
+ PROC(REMOVE, diropargs, wccstat, 0),
+ PROC(RMDIR, diropargs, wccstat, 0),
+ PROC(RENAME, renameargs, renameres, 0),
+ PROC(LINK, linkargs, linkres, 0),
+ PROC(READDIR, readdirargs, readdirres, 3),
+ PROC(READDIRPLUS, readdirargs, readdirres, 3),
+ PROC(FSSTAT, fhandle, fsstatres, 0),
+ PROC(FSINFO, fhandle, fsinfores, 0),
+ PROC(PATHCONF, fhandle, pathconfres, 0),
+ PROC(COMMIT, commitargs, commitres, 5),
+ PROC(GETXATTR, getxattrargs, getxattrres, 1),
+ PROC(SETXATTR, setxattrargs, setxattrres, 0),
+};
+
+struct rpc_version selinux_nfs_version3 = {
+ .number = 3,
+ .nrprocs = sizeof(selinux_nfs3_procedures)/
+ sizeof(selinux_nfs3_procedures[0]),
+ .procs = selinux_nfs3_procedures
+};
+#endif /* CONFIG_NFS_SELINUX */
Index: nfs-2.6/fs/nfs/symlink.c
diff -u nfs-2.6/fs/nfs/symlink.c:1.1.1.2 nfs-2.6/fs/nfs/symlink.c:1.3
--- nfs-2.6/fs/nfs/symlink.c:1.1.1.2 Thu Oct 21 12:02:33 2004
+++ nfs-2.6/fs/nfs/symlink.c Fri Oct 22 16:27:15 2004
@@ -24,6 +24,7 @@
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include <linux/sunrpc/xattr.h>
/* Symlink caching in the page cache is even more simplistic
* and straight-forward than readdir caching.
@@ -114,4 +115,8 @@
.put_link = nfs_put_link,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+#ifdef CONFIG_NFS_XATTR
+ .getxattr = nfs_getxattr,
+ .setxattr = nfs_setxattr,
+#endif
};
Index: nfs-2.6/fs/nfs/xattr.c
diff -u /dev/null nfs-2.6/fs/nfs/xattr.c:1.4
--- /dev/null Mon Jun 20 12:37:15 2005
+++ nfs-2.6/fs/nfs/xattr.c Wed Mar 3 15:40:37 2004
@@ -0,0 +1,62 @@
+/*
+ * File: fs/nfs/xattr.c
+ *
+ * Derived from fs/devpts/xattr.c
+ */
+
+#include <linux/fs.h>
+#include <linux/nfs_fs.h>
+#include <linux/sunrpc/xattr.h>
+
+/*
+ * Inode operation getxattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+
+ssize_t
+nfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ int xattrlen;
+ int error;
+
+ error = -EOPNOTSUPP;
+ if (NFS_PROTO(inode)->getxattr) {
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ error = NFS_PROTO(inode)->getxattr(dentry, name, buffer, size,
+ &xattrlen);
+ }
+ if (error < 0)
+ return (ssize_t)error;
+
+ return (ssize_t)xattrlen;
+}
+
+/*
+ * Inode operation setxattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+int
+nfs_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = -EOPNOTSUPP;
+ if (NFS_PROTO(inode)->setxattr) {
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ if (size == 0)
+ value = ""; /* empty EA, do not remove */
+ if (size > NFS_XATTR_SIZE_MAX)
+ return -EOPNOTSUPP;
+ error = NFS_PROTO(inode)->setxattr(dentry, name, value, size,
+ flags);
+ }
+
+ return error;
+}
Index: nfs-2.6/fs/nfsd/export.c
diff -u nfs-2.6/fs/nfsd/export.c:1.1.1.6 nfs-2.6/fs/nfsd/export.c:1.8
--- nfs-2.6/fs/nfsd/export.c:1.1.1.6 Wed Mar 2 10:21:30 2005
+++ nfs-2.6/fs/nfsd/export.c Wed Mar 2 11:00:43 2005
@@ -1013,6 +1013,7 @@
{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
+ { NFSEXP_SELINUX, {"selinux", ""}},
#ifdef MSNFS
{ NFSEXP_MSNFS, {"msnfs", ""}},
#endif
Index: nfs-2.6/fs/nfsd/nfs3proc.c
diff -u nfs-2.6/fs/nfsd/nfs3proc.c:1.1.1.4 nfs-2.6/fs/nfsd/nfs3proc.c:1.19
--- nfs-2.6/fs/nfsd/nfs3proc.c:1.1.1.4 Thu Oct 21 12:03:18 2004
+++ nfs-2.6/fs/nfsd/nfs3proc.c Wed Mar 30 12:41:41 2005
@@ -24,6 +24,9 @@
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr3.h>
#include <linux/nfs3.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/xattr.h>
+#include <linux/security.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
@@ -57,12 +60,21 @@
struct nfsd3_attrstat *resp)
{
int nfserr;
+ struct svc_fh *fhp;
dprintk("nfsd: GETATTR(3) %s\n",
SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+#ifdef CONFIG_NFSD_SELINUX
+ if (nfserr)
+ RETURN_STATUS(nfserr);
+ fhp = &resp->fh;
+ nfserr = security_inode_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry);
+ if (nfserr)
+ nfserr = nfserrno(nfserr);
+#endif
RETURN_STATUS(nfserr);
}
@@ -630,6 +642,39 @@
RETURN_STATUS(nfserr);
}
+#ifdef CONFIG_NFSD_XATTR
+/*
+ * Get the named Extended Attribute value for the given file
+ */
+static int
+nfsd3_proc_getxattr(struct svc_rqst *rqstp, struct nfsd3_getxattrargs *argp,
+ struct nfsd3_getxattrres *resp)
+{
+ int nfserr;
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_getxattr(rqstp, &resp->fh, argp->name, argp->size,
+ resp->buffer, &resp->xattrlen, &resp->sid);
+ if (argp->size == 0)
+ resp->buflen = 0;
+ else
+ resp->buflen = resp->xattrlen;
+ RETURN_STATUS(nfserr);
+}
+
+/*
+ * Set the named Extended Attribute value for the given file
+ */
+static int
+nfsd3_proc_setxattr(struct svc_rqst *rqstp, struct nfsd3_setxattrargs *argp,
+ struct nfsd3_setxattrres *resp)
+{
+ int nfserr;
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_setxattr(rqstp, &resp->fh, argp->name, argp->value,
+ argp->size, argp->flags, &resp->sid);
+ RETURN_STATUS(nfserr);
+}
+#endif /* CONFIG_NFSD_XATTR */
/*
* NFSv3 Server procedures.
@@ -664,11 +709,12 @@
#define ST 1 /* status*/
#define FH 17 /* filehandle with length */
-#define AT 21 /* attributes */
+#define AT (21 + 1) /* attributes (+1 for SELinux sid) */
#define pAT (1+AT) /* post attributes - conditional */
#define WC (7+pAT) /* WCC attributes */
+#define EA (1+XDR_QUADLEN(NFS_XATTR_SIZE_MAX) + 1) /* xattr */
-static struct svc_procedure nfsd_procedures3[22] = {
+static struct svc_procedure nfsd_procedures3[24] = {
PROC(null, void, void, void, RC_NOCACHE, ST),
PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF, ST+WC),
@@ -700,3 +746,77 @@
.vs_dispatch = nfsd_dispatch,
.vs_xdrsize = NFS3_SVC_XDRSIZE,
};
+
+#ifdef CONFIG_NFSD_SELINUX
+static struct svc_procedure selinux_nfsd_procedures3[24] = {
+ PROC(null, void, void, void, RC_NOCACHE, ST),
+ PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
+ PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
+ PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
+ PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
+ PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+ PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
+ PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(symlink, symlink, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(rename, rename, rename, fhandle2, RC_REPLBUFF, ST+WC+WC),
+ PROC(link, link, link, fhandle2, RC_REPLBUFF, ST+pAT+WC),
+ PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE, 0),
+ PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE, 0),
+ PROC(fsstat, fhandle, fsstat, void, RC_NOCACHE, ST+pAT+2*6+1),
+ PROC(fsinfo, fhandle, fsinfo, void, RC_NOCACHE, ST+pAT+12),
+ PROC(pathconf, fhandle, pathconf, void, RC_NOCACHE, ST+pAT+6),
+ PROC(commit, commit, commit, fhandle, RC_NOCACHE, ST+WC+2),
+ PROC(getxattr, getxattr, getxattr, fhandle, RC_NOCACHE, ST+1+EA),
+ PROC(setxattr, setxattr, setxattr, fhandle, RC_NOCACHE, ST+1),
+};
+
+struct svc_version selinux_nfsd_version3 = {
+ .vs_vers = 3,
+ .vs_nproc = 24,
+ .vs_proc = selinux_nfsd_procedures3,
+ .vs_dispatch = nfsd_dispatch,
+ .vs_xdrsize = NFS3EA_SVC_XDRSIZE,
+};
+#endif /* CONFIG_NFSD_SELINUX */
+
+#ifdef CONFIG_NFSD_XATTR
+static struct svc_procedure xattr_nfsd_procedures3[24] = {
+ PROC(null, void, void, void, RC_NOCACHE, ST),
+ PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
+ PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
+ PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
+ PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
+ PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+ PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
+ PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(symlink, symlink, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+ PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
+ PROC(rename, rename, rename, fhandle2, RC_REPLBUFF, ST+WC+WC),
+ PROC(link, link, link, fhandle2, RC_REPLBUFF, ST+pAT+WC),
+ PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE, 0),
+ PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE, 0),
+ PROC(fsstat, fhandle, fsstat, void, RC_NOCACHE, ST+pAT+2*6+1),
+ PROC(fsinfo, fhandle, fsinfo, void, RC_NOCACHE, ST+pAT+12),
+ PROC(pathconf, fhandle, pathconf, void, RC_NOCACHE, ST+pAT+6),
+ PROC(commit, commit, commit, fhandle, RC_NOCACHE, ST+WC+2),
+ PROC(getxattr, getxattr, getxattr, fhandle, RC_NOCACHE, ST+1+EA),
+ PROC(setxattr, setxattr, setxattr, fhandle, RC_NOCACHE, ST+1),
+};
+
+struct svc_version xattr_nfsd_version3 = {
+ .vs_vers = 3,
+ .vs_nproc = 24,
+ .vs_proc = xattr_nfsd_procedures3,
+ .vs_dispatch = nfsd_dispatch,
+ .vs_xdrsize = NFS3EA_SVC_XDRSIZE,
+};
+#endif /* CONFIG_NFSD_XATTR */
Index: nfs-2.6/fs/nfsd/nfs3xdr.c
diff -u nfs-2.6/fs/nfsd/nfs3xdr.c:1.1.1.8 nfs-2.6/fs/nfsd/nfs3xdr.c:1.22
--- nfs-2.6/fs/nfsd/nfs3xdr.c:1.1.1.8 Wed Mar 2 10:21:29 2005
+++ nfs-2.6/fs/nfsd/nfs3xdr.c Wed Mar 30 11:04:17 2005
@@ -21,6 +21,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/xdr3.h>
+#include <linux/security.h>
#define NFSDDBG_FACILITY NFSDDBG_XDR
@@ -212,6 +213,10 @@
p = encode_time3(p, &fhp->fh_post_atime);
p = encode_time3(p, &fhp->fh_post_mtime);
p = encode_time3(p, &fhp->fh_post_ctime);
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ *p++ = htonl(security_get_inode_sid(inode));
+#endif
return p;
}
@@ -222,10 +227,16 @@
* handle. In this case, no attributes are returned.
*/
static u32 *
-encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{
struct dentry *dentry = fhp->fh_dentry;
- if (dentry && dentry->d_inode != NULL) {
+
+#ifdef CONFIG_NFSD_SELINUX
+ if (dentry && dentry->d_inode != NULL &&
+ !security_inode_getattr(fhp->fh_export->ex_mnt, dentry)) {
+#else
+ if (dentry && dentry->d_inode != NULL {
+#endif
*p++ = xdr_one; /* attributes follow */
return encode_fattr3(rqstp, p, fhp);
}
@@ -233,6 +244,31 @@
return p;
}
+static u32 *
+encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ struct dentry *dentry = fhp->fh_dentry;
+ struct inode *inode = dentry->d_inode;
+
+#ifdef CONFIG_NFSD_SELINUX
+ if (dentry && dentry->d_inode != NULL &&
+ !security_inode_getattr(fhp->fh_export->ex_mnt, dentry)) {
+#else
+ if (dentry && dentry->d_inode != NULL {
+#endif
+ *p++ = xdr_one; /* attributes follow */
+ p = encode_fattr3(rqstp, p, fhp);
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ *p++ = htonl(security_get_inode_sid(inode));
+#endif
+
+ return p;
+ }
+ *p++ = xdr_zero;
+ return p;
+}
+
/*
* Enocde weak cache consistency data
*/
@@ -583,6 +619,34 @@
return xdr_argsize_check(rqstp, p);
}
+#ifdef CONFIG_NFSD_XATTR
+int
+nfs3svc_decode_getxattrargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getxattrargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh)) ||
+ !(p = xdr_decode_string_inplace(p, &args->name, &args->namelen,
+ XATTR_NAME_MAX)))
+ return 0;
+ args->size = ntohl(*p++);
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_setxattrargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_setxattrargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh)) ||
+ !(p = xdr_decode_string_inplace(p, &args->name, &args->namelen,
+ XATTR_NAME_MAX)) ||
+ !(p = xdr_decode_string_inplace(p, &args->value, &args->size,
+ NFS_XATTR_SIZE_MAX)))
+ return 0;
+ args->flags = ntohl(*p++);
+ return xdr_argsize_check(rqstp, p);
+}
+#endif /* CONFIG_NFSD_XATTR */
+
/*
* XDR encode functions
*/
@@ -601,8 +665,16 @@
nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_attrstat *resp)
{
- if (resp->status == 0)
- p = encode_fattr3(rqstp, p, &resp->fh);
+ struct svc_fh *fhp = &resp->fh;
+ struct inode *inode = fhp->fh_dentry->d_inode;
+
+ if (resp->status == 0) {
+ p = encode_fattr3(rqstp, p, fhp);
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ *p++ = htonl(security_get_inode_sid(inode));
+#endif
+ }
return xdr_ressize_check(rqstp, p);
}
@@ -779,7 +851,7 @@
encode_entryplus_baggage(struct nfsd3_readdirres *cd, u32 *p,
struct svc_fh *fhp)
{
- p = encode_post_op_attr(cd->rqstp, p, fhp);
+ p = _encode_post_op_attr(cd->rqstp, p, fhp);
*p++ = xdr_one; /* yes, a file handle follows */
p = encode_fh(p, fhp);
fh_put(fhp);
@@ -1066,6 +1138,34 @@
return xdr_ressize_check(rqstp, p);
}
+#ifdef CONFIG_NFSD_XATTR
+/* GETXATTR */
+int
+nfs3svc_encode_getxattrres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getxattrres *res)
+{
+ *p++ = htonl(res->xattrlen);
+ p = xdr_encode_array(p, res->buffer, res->buflen);
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ *p++ = htonl(res->sid);
+#endif
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* SETXATTR */
+int
+nfs3svc_encode_setxattrres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_setxattrres *res)
+{
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ *p++ = htonl(res->sid);
+#endif
+ return xdr_ressize_check(rqstp, p);
+}
+#endif /* CONFIG_NFSD_XATTR */
+
/*
* XDR release functions
*/
Index: nfs-2.6/fs/nfsd/nfsfh.c
diff -u nfs-2.6/fs/nfsd/nfsfh.c:1.1.1.7 nfs-2.6/fs/nfsd/nfsfh.c:1.13
--- nfs-2.6/fs/nfsd/nfsfh.c:1.1.1.7 Mon Dec 27 16:08:01 2004
+++ nfs-2.6/fs/nfsd/nfsfh.c Wed Mar 30 11:04:18 2005
@@ -177,8 +177,14 @@
if (!exp || IS_ERR(exp))
goto out;
- /* Check if the request originated from a secure port. */
error = nfserr_perm;
+#ifdef CONFIG_NFSD_SELINUX
+ if (EX_SELINUX(exp) && !rqstp->rq_selinux) {
+ printk(KERN_WARNING "nfsd: request not using SELinux\n");
+ goto out;
+ }
+#endif
+ /* Check if the request originated from a secure port. */
if (!rqstp->rq_secure && EX_SECURE(exp)) {
printk(KERN_WARNING
"nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
@@ -330,7 +336,8 @@
(long) exp->ex_dentry->d_inode->i_ino,
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
-
+ dprintk("nfsd: fh_compose: parent ino=%ld\n",
+ (parent->d_inode ? parent->d_inode->i_ino : 0));
if (ref_fh) {
ref_fh_version = ref_fh->fh_handle.fh_version;
if (ref_fh_version == 0xca)
Index: nfs-2.6/fs/nfsd/nfsproc.c
diff -u nfs-2.6/fs/nfsd/nfsproc.c:1.1.1.7 nfs-2.6/fs/nfsd/nfsproc.c:1.7
--- nfs-2.6/fs/nfsd/nfsproc.c:1.1.1.7 Wed Mar 2 10:21:30 2005
+++ nfs-2.6/fs/nfsd/nfsproc.c Wed Mar 2 11:00:43 2005
@@ -580,6 +580,10 @@
{ nfserr_nospc, -ENOSPC },
{ nfserr_rofs, -EROFS },
{ nfserr_mlink, -EMLINK },
+#ifdef CONFIG_NFSD_XATTR
+ { nfserr_erange, -ERANGE },
+ { nfserr_eopnotsupp, -EOPNOTSUPP },
+#endif
{ nfserr_nametoolong, -ENAMETOOLONG },
{ nfserr_notempty, -ENOTEMPTY },
#ifdef EDQUOT
Index: nfs-2.6/fs/nfsd/nfssvc.c
diff -u nfs-2.6/fs/nfsd/nfssvc.c:1.1.1.4 nfs-2.6/fs/nfsd/nfssvc.c:1.14
--- nfs-2.6/fs/nfsd/nfssvc.c:1.1.1.4 Wed Mar 2 10:21:30 2005
+++ nfs-2.6/fs/nfsd/nfssvc.c Wed Mar 2 11:00:43 2005
@@ -31,6 +31,8 @@
#include <linux/nfsd/stats.h>
#include <linux/nfsd/cache.h>
#include <linux/lockd/bind.h>
+#include <linux/sunrpc/xattr.h>
+#include <linux/sunrpc/selinux.h>
#define NFSDDBG_FACILITY NFSDDBG_SVC
@@ -48,7 +50,8 @@
*/
#define SIG_NOCLEAN SIGHUP
-extern struct svc_program nfsd_program;
+extern struct svc_program nfsd_program, selinux_nfsd_program,
+ xattr_nfsd_program;
static void nfsd(struct svc_rqst *rqstp);
struct timeval nfssvc_boot;
static struct svc_serv *nfsd_serv;
@@ -372,6 +375,11 @@
#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
struct svc_program nfsd_program = {
+#ifdef CONFIG_NFSD_XATTR
+ .pg_next = &xattr_nfsd_program, /* next registered program */
+#else
+ .pg_next = NULL,
+#endif
.pg_prog = NFS_PROGRAM, /* program number */
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
.pg_vers = nfsd_version, /* version table */
@@ -379,3 +387,43 @@
.pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */
};
+
+#ifdef CONFIG_NFSD_XATTR
+extern struct svc_version xattr_nfsd_version3;
+static struct svc_version * xattr_nfsd_version[] = {
+ [3] = &xattr_nfsd_version3,
+};
+#define XATTR_NFSD_NRVERS (sizeof(xattr_nfsd_version)/sizeof(xattr_nfsd_version[0]))
+
+struct svc_program xattr_nfsd_program = {
+#ifdef CONFIG_NFSD_SELINUX
+ .pg_next = &selinux_nfsd_program, /* next registered program */
+#else
+ .pg_next = NULL,
+#endif
+ .pg_prog = XATTR_NFS_PROGRAM, /* program number */
+ .pg_nvers = XATTR_NFSD_NRVERS, /* nr of entries in nfsd_version */
+ .pg_vers = xattr_nfsd_version, /* version table */
+ .pg_name = "xattr_nfsd", /* program name */
+ .pg_class = "xattr_nfsd", /* authentication class */
+ .pg_stats = &xattr_nfsd_svcstats,
+};
+#endif /* CONFIG_NFSD_XATTR */
+
+#ifdef CONFIG_NFSD_SELINUX
+extern struct svc_version selinux_nfsd_version3;
+static struct svc_version * selinux_nfsd_version[] = {
+ [3] = &selinux_nfsd_version3,
+};
+#define SELINUX_NFSD_NRVERS (sizeof(selinux_nfsd_version)/sizeof(selinux_nfsd_version[0]))
+
+struct svc_program selinux_nfsd_program = {
+ .pg_next = NULL, /* next registered program */
+ .pg_prog = SELINUX_NFS_PROGRAM, /* program number */
+ .pg_nvers = SELINUX_NFSD_NRVERS, /* nr of entries in nfsd_version */
+ .pg_vers = selinux_nfsd_version, /* version table */
+ .pg_name = "selinux_nfsd", /* program name */
+ .pg_class = "selinux_nfsd", /* authentication class */
+ .pg_stats = &selinux_nfsd_svcstats,
+};
+#endif /* CONFIG_NFSD_SELINUX */
Index: nfs-2.6/fs/nfsd/stats.c
diff -u nfs-2.6/fs/nfsd/stats.c:1.1.1.2 nfs-2.6/fs/nfsd/stats.c:1.4
--- nfs-2.6/fs/nfsd/stats.c:1.1.1.2 Fri Apr 2 14:13:50 2004
+++ nfs-2.6/fs/nfsd/stats.c Mon Apr 5 09:35:36 2004
@@ -39,6 +39,17 @@
struct svc_stat nfsd_svcstats = {
.program = &nfsd_program,
};
+#ifdef CONFIG_NFSD_SELINUX
+struct svc_stat selinux_nfsd_svcstats = {
+ .program = &selinux_nfsd_program,
+};
+#endif
+
+#ifdef CONFIG_NFSD_XATTR
+struct svc_stat xattr_nfsd_svcstats = {
+ .program = &xattr_nfsd_program,
+};
+#endif
static int nfsd_proc_show(struct seq_file *seq, void *v)
{
@@ -71,7 +82,14 @@
/* show my rpc info */
svc_seq_show(seq, &nfsd_svcstats);
-
+#ifdef CONFIG_NFSD_XATTR
+ seq_printf(seq,"xattr:\n");
+ svc_seq_show(seq, &xattr_nfsd_svcstats);
+#endif
+#ifdef CONFIG_NFSD_SELINUX
+ seq_printf(seq,"selinux:\n");
+ svc_seq_show(seq, &selinux_nfsd_svcstats);
+#endif
return 0;
}
Index: nfs-2.6/fs/nfsd/vfs.c
diff -u nfs-2.6/fs/nfsd/vfs.c:1.1.1.10 nfs-2.6/fs/nfsd/vfs.c:1.22
--- nfs-2.6/fs/nfsd/vfs.c:1.1.1.10 Wed Mar 2 10:21:30 2005
+++ nfs-2.6/fs/nfsd/vfs.c Wed Mar 30 12:41:41 2005
@@ -53,8 +53,8 @@
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
#include <linux/nfsd_idmap.h>
-#include <linux/security.h>
#endif /* CONFIG_NFSD_V4 */
+#include <linux/security.h>
#include <asm/uaccess.h>
@@ -1767,8 +1767,14 @@
* with NFSv3.
*/
if ((acc & MAY_OWNER_OVERRIDE) &&
- inode->i_uid == current->fsuid)
- return 0;
+ inode->i_uid == current->fsuid) {
+#ifdef CONFIG_NFSD_SELINUX
+ err = security_inode_permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
+#else
+ err = 0;
+#endif
+ return err ? nfserrno(err) : 0;
+ }
err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
@@ -1817,3 +1823,85 @@
nfsdstats.ra_size = cache_size;
return 0;
}
+
+#ifdef CONFIG_NFSD_XATTR
+/*
+ * Get file extended attribute
+ * After this call fhp needs an fh_put
+ */
+int
+nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
+ u32 size, char *buffer, int *xattrlen, u32 *sid)
+{
+ struct dentry *dentry;
+ int error;
+
+ *xattrlen = 0;
+ *sid = 0;
+ error = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (error)
+ return error;
+ dentry = fhp->fh_dentry;
+ error = nfserr_eopnotsupp;
+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->getxattr) {
+ error = security_inode_getxattr(dentry, name);
+ if (error)
+ return nfserrno(error);
+ if (size == 0)
+ buffer = NULL;
+ if (size > NFS_XATTR_SIZE_MAX) {
+ *xattrlen = dentry->d_inode->i_op->getxattr(dentry, name,
+ NULL, size);
+ if (*xattrlen > NFS_XATTR_SIZE_MAX){
+ *xattrlen = 0;
+ return nfserrno(-EOPNOTSUPP);
+ }
+ }
+ *xattrlen = dentry->d_inode->i_op->getxattr(dentry, name,
+ buffer, size);
+ if (*xattrlen < 0) {
+ error = *xattrlen;
+ *xattrlen = 0;
+ return nfserrno(error);
+ }
+ if ((strcmp(name, XATTR_NAME_SELINUX) == 0) &&
+ rqstp->rq_selinux)
+ *sid = security_get_inode_sid(dentry->d_inode);
+ }
+ return error;
+}
+
+/*
+ * Set file extended attribute
+ * After this call fhp needs an fh_put
+ */
+int
+nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
+ char *value, u32 size, int flags, u32 *sid)
+{
+ struct dentry *dentry;
+ int error;
+
+ *sid = 0;
+ error = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (error)
+ return error;
+ dentry = fhp->fh_dentry;
+ error = nfserr_eopnotsupp;
+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setxattr) {
+ error = security_inode_setxattr(dentry, name, value, size, flags);
+ if (error)
+ return nfserrno(error);
+ error = dentry->d_inode->i_op->setxattr(dentry, name, value,
+ size, flags);
+ if (error)
+ return nfserrno(error);
+ security_inode_post_setxattr(dentry, name, value, size,
+ flags);
+ if ((strcmp(name, XATTR_NAME_SELINUX) == 0) &&
+ rqstp->rq_selinux)
+ *sid = security_get_inode_sid(dentry->d_inode);
+ }
+ return error;
+}
+#endif /* CONFIG_NFSD_XATTR */
Index: nfs-2.6/include/linux/nfs.h
diff -u nfs-2.6/include/linux/nfs.h:1.1.1.3 nfs-2.6/include/linux/nfs.h:1.4
--- nfs-2.6/include/linux/nfs.h:1.1.1.3 Thu Oct 21 11:47:43 2004
+++ nfs-2.6/include/linux/nfs.h Fri Oct 22 16:27:18 2004
@@ -57,12 +57,14 @@
NFSERR_NOSPC = 28, /* v2 v3 v4 */
NFSERR_ROFS = 30, /* v2 v3 v4 */
NFSERR_MLINK = 31, /* v3 v4 */
+ NFSERR_ERANGE = 34, /* v3ea */
NFSERR_OPNOTSUPP = 45, /* v2 v3 */
NFSERR_NAMETOOLONG = 63, /* v2 v3 v4 */
NFSERR_NOTEMPTY = 66, /* v2 v3 v4 */
NFSERR_DQUOT = 69, /* v2 v3 v4 */
NFSERR_STALE = 70, /* v2 v3 v4 */
NFSERR_REMOTE = 71, /* v2 v3 */
+ NFSERR_EOPNOTSUPP = 95, /* v3ea */
NFSERR_WFLUSH = 99, /* v2 */
NFSERR_BADHANDLE = 10001, /* v3 v4 */
NFSERR_NOT_SYNC = 10002, /* v3 */
Index: nfs-2.6/include/linux/nfs3.h
diff -u nfs-2.6/include/linux/nfs3.h:1.1.1.1 nfs-2.6/include/linux/nfs3.h:1.2
--- nfs-2.6/include/linux/nfs3.h:1.1.1.1 Mon Aug 18 12:47:53 2003
+++ nfs-2.6/include/linux/nfs3.h Wed Nov 26 14:19:57 2003
@@ -87,6 +87,8 @@
#define NFS3PROC_FSINFO 19
#define NFS3PROC_PATHCONF 20
#define NFS3PROC_COMMIT 21
+#define NFS3PROC_GETXATTR 22
+#define NFS3PROC_SETXATTR 23
#define NFS_MNT3_PROGRAM 100005
#define NFS_MNT3_VERSION 3
Index: nfs-2.6/include/linux/nfs_fs.h
diff -u nfs-2.6/include/linux/nfs_fs.h:1.1.1.8 nfs-2.6/include/linux/nfs_fs.h:1.10
--- nfs-2.6/include/linux/nfs_fs.h:1.1.1.8 Wed Mar 2 10:30:14 2005
+++ nfs-2.6/include/linux/nfs_fs.h Fri Mar 18 10:20:42 2005
@@ -190,6 +190,8 @@
struct rw_semaphore rwsem;
#endif /* CONFIG_NFS_V4*/
+ /* Security id passed back from the server */
+ __u32 sid;
struct inode vfs_inode;
};
@@ -203,6 +205,7 @@
#define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */
#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */
#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */
+#define NFS_INO_INVALID_XATTR 0x1000 /* SELinux Security Context invalid */
static inline struct nfs_inode *NFS_I(struct inode *inode)
{
Index: nfs-2.6/include/linux/nfs_mount.h
diff -u nfs-2.6/include/linux/nfs_mount.h:1.1.1.2 nfs-2.6/include/linux/nfs_mount.h:1.5
--- nfs-2.6/include/linux/nfs_mount.h:1.1.1.2 Thu Feb 19 14:08:42 2004
+++ nfs-2.6/include/linux/nfs_mount.h Mon May 10 15:19:29 2004
@@ -60,6 +60,8 @@
#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */
#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */
#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
-#define NFS_MOUNT_FLAGMASK 0xFFFF
+#define NFS_MOUNT_XATTR 0x100000 /* xattr */
+#define NFS_MOUNT_SELINUX 0x200000 /* SELinux */
+#define NFS_MOUNT_FLAGMASK 0x30FFFF
#endif
Index: nfs-2.6/include/linux/nfs_xdr.h
diff -u nfs-2.6/include/linux/nfs_xdr.h:1.1.1.7 nfs-2.6/include/linux/nfs_xdr.h:1.14
--- nfs-2.6/include/linux/nfs_xdr.h:1.1.1.7 Wed Mar 2 10:30:30 2005
+++ nfs-2.6/include/linux/nfs_xdr.h Wed Mar 30 09:51:36 2005
@@ -37,6 +37,7 @@
struct timespec atime;
struct timespec mtime;
struct timespec ctime;
+ __u32 sid; /* For SELinux */
__u32 bitmap[2]; /* NFSv4 returned attribute bitmap */
__u64 change_attr; /* NFSv4 change attribute */
__u64 pre_change_attr;/* pre-op NFSv4 change attribute */
@@ -48,6 +49,8 @@
#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */
#define NFS_ATTR_FATTR_V4 0x0008
#define NFS_ATTR_PRE_CHANGE 0x0010
+#define NFS_XATTR_WCC 0x0100
+#define NFS_XATTR_FATTR 0x0200
/*
* Info on the file system
@@ -443,6 +446,24 @@
struct page ** pages;
};
+#ifdef CONFIG_NFS_XATTR
+struct nfs3_getxattrargs {
+ struct nfs_fh * fh;
+ const char * name;
+ unsigned int namelen;
+ unsigned int bufsize;
+};
+
+struct nfs3_setxattrargs {
+ struct nfs_fh * fh;
+ const char * name;
+ unsigned int namelen;
+ const char * value;
+ int size;
+ int flags;
+};
+#endif /* CONFIG_NFS_XATTR */
+
struct nfs3_diropres {
struct nfs_fattr * dir_attr;
struct nfs_fh * fh;
@@ -477,6 +498,19 @@
int plus;
};
+#ifdef CONFIG_NFS_XATTR
+struct nfs3_getxattrres {
+ char * buffer;
+ unsigned int size;
+ unsigned int * xattrlen;
+ __u32 * sid;
+};
+
+struct nfs3_setxattrres {
+ __u32 * sid;
+};
+#endif /* CONFIG_NFS_XATTR */
+
#ifdef CONFIG_NFS_V4
typedef u64 clientid4;
@@ -710,6 +744,12 @@
void (*read_setup) (struct nfs_read_data *);
void (*write_setup) (struct nfs_write_data *, int how);
void (*commit_setup) (struct nfs_write_data *, int how);
+#ifdef CONFIG_NFS_XATTR
+ int (*getxattr) (struct dentry *, const char *, void *, unsigned int,
+ unsigned int *);
+ int (*setxattr) (struct dentry *, const char *, const void *,
+ unsigned int, int);
+#endif
int (*file_open) (struct inode *, struct file *);
int (*file_release) (struct inode *, struct file *);
int (*lock)(struct file *, int, struct file_lock *);
@@ -733,5 +773,16 @@
extern struct rpc_version nfs_version4;
extern struct rpc_program nfs_program;
extern struct rpc_stat nfs_rpcstat;
-
+#ifdef CONFIG_NFS_XATTR
+extern struct nfs_rpc_ops nfs_v3ea_clientops;
+extern struct rpc_version xattr_nfs_version3;
+extern struct rpc_program xattr_nfs_program;
+extern struct rpc_stat xattr_rpcstat;
+#endif /* CONFIG_NFS_XATTR */
+#ifdef CONFIG_NFS_SELINUX
+extern struct nfs_rpc_ops nfs_v3se_clientops;
+extern struct rpc_version selinux_nfs_version3;
+extern struct rpc_program selinux_nfs_program;
+extern struct rpc_stat selinux_rpcstat;
+#endif /* CONFIG_NFS_SELINUX */
#endif
Index: nfs-2.6/include/linux/nfsd/export.h
diff -u nfs-2.6/include/linux/nfsd/export.h:1.1.1.3 nfs-2.6/include/linux/nfsd/export.h:1.5
--- nfs-2.6/include/linux/nfsd/export.h:1.1.1.3 Wed Jun 16 13:18:25 2004
+++ nfs-2.6/include/linux/nfsd/export.h Fri Jun 18 09:43:42 2004
@@ -40,7 +40,8 @@
#define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
-#define NFSEXP_ALLFLAGS 0xFE3F
+#define NFSEXP_SELINUX 0x100000
+#define NFSEXP_ALLFLAGS 0x10FE3F
#ifdef __KERNEL__
@@ -75,6 +76,7 @@
#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY)
#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+#define EX_SELINUX(exp) ((exp)->ex_flags & NFSEXP_SELINUX)
/*
Index: nfs-2.6/include/linux/nfsd/nfsd.h
diff -u nfs-2.6/include/linux/nfsd/nfsd.h:1.1.1.7 nfs-2.6/include/linux/nfsd/nfsd.h:1.14
--- nfs-2.6/include/linux/nfsd/nfsd.h:1.1.1.7 Thu Oct 21 11:47:59 2004
+++ nfs-2.6/include/linux/nfsd/nfsd.h Wed Mar 30 11:04:20 2005
@@ -60,6 +60,15 @@
extern struct svc_version nfsd_version2, nfsd_version3,
nfsd_version4;
+#ifdef CONFIG_NFSD_XATTR
+extern struct svc_program xattr_nfsd_program;
+extern struct svc_version xattr_nfsd_version3;
+#endif
+#ifdef CONFIG_NFSD_SELINUX
+extern struct svc_program selinux_nfsd_program;
+extern struct svc_version selinux_nfsd_version3;
+#endif
+
/*
* Function prototypes.
*/
@@ -123,6 +132,12 @@
int nfsd_notify_change(struct inode *, struct iattr *);
int nfsd_permission(struct svc_export *, struct dentry *, int);
+#ifdef CONFIG_NFSD_XATTR
+int nfsd_getxattr(struct svc_rqst *, struct svc_fh *, char *,
+ u32, char *, int *, u32 *);
+int nfsd_setxattr(struct svc_rqst *, struct svc_fh *, char *,
+ char *, u32, int, u32 *);
+#endif
/*
@@ -167,12 +182,14 @@
#define nfserr_nospc __constant_htonl(NFSERR_NOSPC)
#define nfserr_rofs __constant_htonl(NFSERR_ROFS)
#define nfserr_mlink __constant_htonl(NFSERR_MLINK)
+#define nfserr_erange __constant_htonl(NFSERR_ERANGE)
#define nfserr_opnotsupp __constant_htonl(NFSERR_OPNOTSUPP)
#define nfserr_nametoolong __constant_htonl(NFSERR_NAMETOOLONG)
#define nfserr_notempty __constant_htonl(NFSERR_NOTEMPTY)
#define nfserr_dquot __constant_htonl(NFSERR_DQUOT)
#define nfserr_stale __constant_htonl(NFSERR_STALE)
#define nfserr_remote __constant_htonl(NFSERR_REMOTE)
+#define nfserr_eopnotsupp __constant_htonl(NFSERR_EOPNOTSUPP)
#define nfserr_wflush __constant_htonl(NFSERR_WFLUSH)
#define nfserr_badhandle __constant_htonl(NFSERR_BADHANDLE)
#define nfserr_notsync __constant_htonl(NFSERR_NOT_SYNC)
Index: nfs-2.6/include/linux/nfsd/stats.h
diff -u nfs-2.6/include/linux/nfsd/stats.h:1.1.1.1 nfs-2.6/include/linux/nfsd/stats.h:1.3
--- nfs-2.6/include/linux/nfsd/stats.h:1.1.1.1 Mon Aug 18 12:47:57 2003
+++ nfs-2.6/include/linux/nfsd/stats.h Wed Mar 3 15:53:35 2004
@@ -36,6 +36,13 @@
extern struct nfsd_stats nfsdstats;
extern struct svc_stat nfsd_svcstats;
+#ifdef CONFIG_NFSD_XATTR
+extern struct svc_stat xattr_nfsd_svcstats;
+#endif
+#ifdef CONFIG_NFSD_SELINUX
+extern struct svc_stat selinux_nfsd_svcstats;
+#endif
+
void nfsd_stat_init(void);
void nfsd_stat_shutdown(void);
Index: nfs-2.6/include/linux/nfsd/xdr3.h
diff -u nfs-2.6/include/linux/nfsd/xdr3.h:1.1.1.3 nfs-2.6/include/linux/nfsd/xdr3.h:1.9
--- nfs-2.6/include/linux/nfsd/xdr3.h:1.1.1.3 Tue Aug 17 13:52:34 2004
+++ nfs-2.6/include/linux/nfsd/xdr3.h Wed Mar 30 11:04:20 2005
@@ -10,6 +10,8 @@
#define _LINUX_NFSD_XDR3_H
#include <linux/nfsd/xdr.h>
+#include <linux/sunrpc/xattr.h>
+#include <linux/sunrpc/selinux.h>
struct nfsd3_sattrargs {
struct svc_fh fh;
@@ -110,6 +112,24 @@
__u32 count;
};
+#ifdef CONFIG_NFSD_XATTR
+struct nfsd3_getxattrargs {
+ struct svc_fh fh;
+ char * name;
+ __u32 namelen;
+ __u32 size;
+};
+
+struct nfsd3_setxattrargs {
+ struct svc_fh fh;
+ char * name;
+ __u32 namelen;
+ char * value;
+ __u32 size;
+ int flags;
+};
+#endif /* CONFIG_NFSD_XATTR */
+
struct nfsd3_attrstat {
__u32 status;
struct svc_fh fh;
@@ -209,6 +229,24 @@
struct svc_fh fh;
};
+#ifdef CONFIG_NFSD_XATTR
+struct nfsd3_getxattrres {
+ __u32 status;
+ struct svc_fh fh;
+ int xattrlen;
+ char buffer[NFS_XATTR_SIZE_MAX];
+ __u32 buflen;
+ __u32 sid;
+
+};
+
+struct nfsd3_setxattrres {
+ __u32 status;
+ struct svc_fh fh;
+ __u32 sid;
+};
+#endif /* CONFIG_NFSD_XATTR */
+
/* dummy type for release */
struct nfsd3_fhandle_pair {
__u32 dummy;
@@ -245,6 +283,38 @@
#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
+#ifdef CONFIG_NFSD_XATTR
+union nfsd3ea_xdrstore {
+ struct nfsd3_sattrargs sattrargs;
+ struct nfsd3_diropargs diropargs;
+ struct nfsd3_readargs readargs;
+ struct nfsd3_writeargs writeargs;
+ struct nfsd3_createargs createargs;
+ struct nfsd3_renameargs renameargs;
+ struct nfsd3_linkargs linkargs;
+ struct nfsd3_symlinkargs symlinkargs;
+ struct nfsd3_readdirargs readdirargs;
+ struct nfsd3_getxattrargs getxattrargs;
+ struct nfsd3_setxattrargs setxattrargs;
+ struct nfsd3_diropres diropres;
+ struct nfsd3_accessres accessres;
+ struct nfsd3_readlinkres readlinkres;
+ struct nfsd3_readres readres;
+ struct nfsd3_writeres writeres;
+ struct nfsd3_renameres renameres;
+ struct nfsd3_linkres linkres;
+ struct nfsd3_readdirres readdirres;
+ struct nfsd3_fsstatres fsstatres;
+ struct nfsd3_fsinfores fsinfores;
+ struct nfsd3_pathconfres pathconfres;
+ struct nfsd3_commitres commitres;
+ struct nfsd3_getxattrres getxattrres;
+ struct nfsd3_setxattrres setxattrres;
+};
+
+#define NFS3EA_SVC_XDRSIZE sizeof(union nfsd3ea_xdrstore)
+#endif /* CONFIG_NFSD_XATTR */
+
int nfs3svc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
int nfs3svc_decode_sattrargs(struct svc_rqst *, u32 *,
struct nfsd3_sattrargs *);
@@ -276,6 +346,12 @@
struct nfsd3_readdirargs *);
int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *,
struct nfsd3_commitargs *);
+#ifdef CONFIG_NFSD_XATTR
+int nfs3svc_decode_getxattrargs(struct svc_rqst *, u32 *,
+ struct nfsd3_getxattrargs *);
+int nfs3svc_decode_setxattrargs(struct svc_rqst *, u32 *,
+ struct nfsd3_setxattrargs *);
+#endif
int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *);
int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *,
struct nfsd3_attrstat *);
@@ -305,7 +381,12 @@
struct nfsd3_pathconfres *);
int nfs3svc_encode_commitres(struct svc_rqst *, u32 *,
struct nfsd3_commitres *);
-
+#ifdef CONFIG_NFSD_XATTR
+int nfs3svc_encode_getxattrres(struct svc_rqst *, u32 *,
+ struct nfsd3_getxattrres *);
+int nfs3svc_encode_setxattrres(struct svc_rqst *, u32 *,
+ struct nfsd3_setxattrres *);
+#endif
int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
struct nfsd3_attrstat *);
int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
Index: nfs-2.6/include/linux/sunrpc/auth.h
diff -u nfs-2.6/include/linux/sunrpc/auth.h:1.1.1.4 nfs-2.6/include/linux/sunrpc/auth.h:1.3
--- nfs-2.6/include/linux/sunrpc/auth.h:1.1.1.4 Wed Mar 2 10:30:49 2005
+++ nfs-2.6/include/linux/sunrpc/auth.h Wed Mar 2 11:00:49 2005
@@ -46,6 +46,7 @@
#endif
uid_t cr_uid;
+ u32 cr_sid;
/* per-flavor data */
};
Index: nfs-2.6/include/linux/sunrpc/clnt.h
diff -u nfs-2.6/include/linux/sunrpc/clnt.h:1.1.1.2 nfs-2.6/include/linux/sunrpc/clnt.h:1.3
--- nfs-2.6/include/linux/sunrpc/clnt.h:1.1.1.2 Thu Feb 19 14:09:01 2004
+++ nfs-2.6/include/linux/sunrpc/clnt.h Fri Feb 20 08:33:00 2004
@@ -53,7 +53,8 @@
cl_autobind : 1,/* use getport() */
cl_droppriv : 1,/* enable NFS suid hack */
cl_oneshot : 1,/* dispose after use */
- cl_dead : 1;/* abandoned */
+ cl_dead : 1,/* abandoned */
+ cl_selinux : 1;/* Use SELinux */
struct rpc_rtt * cl_rtt; /* RTO estimator data */
struct rpc_portmap * cl_pmap; /* port mapping */
Index: nfs-2.6/include/linux/sunrpc/selinux.h
diff -u /dev/null nfs-2.6/include/linux/sunrpc/selinux.h:1.11
--- /dev/null Mon Jun 20 12:38:29 2005
+++ nfs-2.6/include/linux/sunrpc/selinux.h Fri Mar 18 10:20:43 2005
@@ -0,0 +1,61 @@
+/* -*- linux-c -*- */
+
+#ifndef _SELINUX_RPC_H_
+#define _SELINUX_RPC_H_
+
+
+#include <linux/types.h>
+#include <linux/xattr.h>
+
+#define SELINUX_NFS_PROGRAM 100006
+
+#define SELINUX_RPC_MAXCONTEXTLEN 255
+/* Size is 4 for length + Max length of context + 1 for \0*/
+#define SELINUX_RPC_SZ (SELINUX_RPC_MAXCONTEXTLEN + 5)
+#define SELINUX_RPC_WORDS ((SELINUX_RPC_SZ+3)>>2)
+
+#define XATTR_SELINUX_SUFFIX "selinux"
+#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
+
+#ifdef CONFIG_SECURITY_SELINUX
+int security_sid_to_network_context(u32 sid, char *context,
+ u32 *len);
+int security_network_context_to_sid(char *context, u32 len,
+ u32 *sid);
+u32 security_get_task_sid(void);
+u32 security_get_inode_sid(struct inode *inode);
+void security_set_fssid(u32 sid);
+void security_clear_fssid(void);
+int security_revalidate_inode(struct inode *inode);
+
+#else /* CONFIG_SECURITY_SELINUX not defined */
+static inline int security_sid_to_network_context(u32 sid, char *context, u32 *len)
+{
+ *len = 0;
+ return -EOPNOTSUPP;
+}
+static inline int security_network_context_to_sid(char *context, u32 len, u32 *sid)
+{
+ *sid = 0;
+ return -EOPNOTSUPP;
+}
+static inline u32 security_get_task_sid(void)
+{
+ return 0;
+}
+static inline u32 security_get_inode_sid(struct inode *inode)
+{
+ return 0;
+}
+static inline int security_set_fssid(u32 sid)
+{
+ return 0;
+}
+static inline void security_clear_fssid(void){}
+static inline int security_revalidate_inode(struct inode *inode)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_SELINUX */
+
+#endif
Index: nfs-2.6/include/linux/sunrpc/svc.h
diff -u nfs-2.6/include/linux/sunrpc/svc.h:1.1.1.5 nfs-2.6/include/linux/sunrpc/svc.h:1.8
--- nfs-2.6/include/linux/sunrpc/svc.h:1.1.1.5 Thu Oct 21 11:47:58 2004
+++ nfs-2.6/include/linux/sunrpc/svc.h Fri Oct 22 16:27:19 2004
@@ -136,7 +136,8 @@
u32 rq_proc; /* procedure number */
u32 rq_prot; /* IP protocol */
unsigned short
- rq_secure : 1; /* secure port */
+ rq_secure : 1, /* secure port */
+ rq_selinux : 1; /* Use SELinux */
__u32 rq_daddr; /* dest addr of request - reply from here */
@@ -159,6 +160,7 @@
* determine what device number
* to report (real or virtual)
*/
+ u32 rq_sid; /* SELinux SID */
wait_queue_head_t rq_wait; /* synchronization */
};
@@ -243,6 +245,7 @@
* RPC program
*/
struct svc_program {
+ struct svc_program * pg_next; /* other programs */
u32 pg_prog; /* program number */
unsigned int pg_lovers; /* lowest version */
unsigned int pg_hivers; /* lowest version */
Index: nfs-2.6/include/linux/sunrpc/xattr.h
diff -u /dev/null nfs-2.6/include/linux/sunrpc/xattr.h:1.1
--- /dev/null Mon Jun 20 12:38:30 2005
+++ nfs-2.6/include/linux/sunrpc/xattr.h Thu Jan 15 16:14:59 2004
@@ -0,0 +1,10 @@
+/*
+ File: include/linux/sunrpc/xattr.h
+
+*/
+
+#define XATTR_NFS_PROGRAM 100007
+#define NFS_XATTR_SIZE_MAX 1024
+
+extern int nfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
+extern ssize_t nfs_getxattr(struct dentry *, const char *, void *, size_t);
Index: nfs-2.6/net/sunrpc/auth.c
diff -u nfs-2.6/net/sunrpc/auth.c:1.1.1.4 nfs-2.6/net/sunrpc/auth.c:1.5
--- nfs-2.6/net/sunrpc/auth.c:1.1.1.4 Wed Mar 2 10:33:06 2005
+++ nfs-2.6/net/sunrpc/auth.c Wed Mar 30 12:41:41 2005
@@ -14,6 +14,7 @@
#include <linux/socket.h>
#include <linux/sunrpc/clnt.h>
#include <linux/spinlock.h>
+#include <linux/sunrpc/selinux.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -204,7 +205,11 @@
struct rpc_cred *new = NULL,
*cred = NULL;
int nr = 0;
+#ifdef CONFIG_NFS_SELINUX
+ u32 sid;
+ sid = security_get_task_sid();
+#endif
if (!(taskflags & RPC_TASK_ROOTCREDS))
nr = acred->uid & RPC_CREDCACHE_MASK;
retry:
@@ -216,6 +221,10 @@
entry = list_entry(pos, struct rpc_cred, cr_hash);
if (rpcauth_prune_expired(entry, &free))
continue;
+#ifdef CONFIG_NFS_SELINUX
+ if (entry->cr_sid != sid)
+ continue;
+#endif
if (entry->cr_ops->crmatch(acred, entry, taskflags)) {
list_del(&entry->cr_hash);
cred = entry;
@@ -243,6 +252,9 @@
#ifdef RPC_DEBUG
new->cr_magic = RPCAUTH_CRED_MAGIC;
#endif
+#ifdef CONFIG_NFS_SELINUX
+ new->cr_sid = sid;
+#endif
goto retry;
}
}
Index: nfs-2.6/net/sunrpc/clnt.c
diff -u nfs-2.6/net/sunrpc/clnt.c:1.1.1.8 nfs-2.6/net/sunrpc/clnt.c:1.22
--- nfs-2.6/net/sunrpc/clnt.c:1.1.1.8 Wed Mar 2 10:33:06 2005
+++ nfs-2.6/net/sunrpc/clnt.c Wed Mar 30 12:41:41 2005
@@ -34,6 +34,7 @@
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/nfs.h>
+#include <linux/sunrpc/selinux.h>
#define RPC_SLACK_SPACE (1024) /* total overkill */
@@ -948,6 +949,11 @@
struct rpc_xprt *xprt = clnt->cl_xprt;
struct rpc_rqst *req = task->tk_rqstp;
u32 *p = req->rq_svec[0].iov_base;
+#ifdef CONFIG_NFS_SELINUX
+ u32 sid, len, quadlen;
+ char *context;
+ int rc;
+#endif
/* FIXME: check buffer size? */
if (xprt->stream)
@@ -958,7 +964,20 @@
*p++ = htonl(clnt->cl_prog); /* program number */
*p++ = htonl(clnt->cl_vers); /* program version */
*p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */
- return rpcauth_marshcred(task, p);
+ p = rpcauth_marshcred(task, p);
+#ifdef CONFIG_NFS_SELINUX
+ if (clnt->cl_selinux) {
+ sid = security_get_task_sid();
+ context = (char *)(p+1);
+ rc = security_sid_to_network_context(sid, context, &len);
+ if (rc)
+ rpc_exit(task, rc);
+ quadlen = XDR_QUADLEN(len);
+ *p++ = htonl(len);
+ p += quadlen;
+ }
+#endif
+ return p;
}
/*
Index: nfs-2.6/net/sunrpc/rpc_pipe.c
diff -u nfs-2.6/net/sunrpc/rpc_pipe.c:1.1.1.7 nfs-2.6/net/sunrpc/rpc_pipe.c:1.13
--- nfs-2.6/net/sunrpc/rpc_pipe.c:1.1.1.7 Wed Mar 2 10:33:05 2005
+++ nfs-2.6/net/sunrpc/rpc_pipe.c Wed Mar 2 11:00:50 2005
@@ -353,6 +353,12 @@
RPCAUTH_mount,
RPCAUTH_nfs,
RPCAUTH_portmap,
+#ifdef CONFIG_NFS_SELINUX
+ RPCAUTH_selinuxnfs,
+#endif
+#ifdef CONFIG_NFS_XATTR
+ RPCAUTH_xattrnfs,
+#endif
RPCAUTH_statd,
RPCAUTH_RootEOF
};
@@ -383,6 +389,18 @@
.name = "portmap",
.mode = S_IFDIR | S_IRUGO | S_IXUGO,
},
+#ifdef CONFIG_NFS_SELINUX
+ [RPCAUTH_selinuxnfs] = {
+ .name = "selinuxnfs",
+ .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+ },
+#endif
+#ifdef CONFIG_NFS_XATTR
+ [RPCAUTH_xattrnfs] = {
+ .name = "xattrnfs",
+ .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+ },
+#endif
[RPCAUTH_statd] = {
.name = "statd",
.mode = S_IFDIR | S_IRUGO | S_IXUGO,
Index: nfs-2.6/net/sunrpc/svc.c
diff -u nfs-2.6/net/sunrpc/svc.c:1.1.1.4 nfs-2.6/net/sunrpc/svc.c:1.23
--- nfs-2.6/net/sunrpc/svc.c:1.1.1.4 Thu Oct 21 11:45:22 2004
+++ nfs-2.6/net/sunrpc/svc.c Wed Mar 30 12:41:42 2005
@@ -18,6 +18,7 @@
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/selinux.h>
#define RPCDBG_FACILITY RPCDBG_SVCDSP
#define RPC_PARANOIA 1
@@ -29,6 +30,7 @@
svc_create(struct svc_program *prog, unsigned int bufsize)
{
struct svc_serv *serv;
+ struct svc_program *progp;
int vers;
unsigned int xdrsize;
@@ -41,14 +43,16 @@
serv->sv_bufsz = bufsize? bufsize : 4096;
prog->pg_lovers = prog->pg_nvers-1;
xdrsize = 0;
- for (vers=0; vers<prog->pg_nvers ; vers++)
- if (prog->pg_vers[vers]) {
- prog->pg_hivers = vers;
- if (prog->pg_lovers > vers)
- prog->pg_lovers = vers;
- if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
- xdrsize = prog->pg_vers[vers]->vs_xdrsize;
- }
+ for (progp = prog; progp; progp = progp->pg_next) {
+ for (vers=0; vers<progp->pg_nvers ; vers++)
+ if (progp->pg_vers[vers]) {
+ progp->pg_hivers = vers;
+ if (progp->pg_lovers > vers)
+ prog->pg_lovers = vers;
+ if (progp->pg_vers[vers]->vs_xdrsize > xdrsize)
+ xdrsize = progp->pg_vers[vers]->vs_xdrsize;
+ }
+ }
serv->sv_xdrsize = xdrsize;
INIT_LIST_HEAD(&serv->sv_threads);
INIT_LIST_HEAD(&serv->sv_sockets);
@@ -227,15 +231,17 @@
if (!port)
clear_thread_flag(TIF_SIGPENDING);
- for (i = 0; i < progp->pg_nvers; i++) {
- if (progp->pg_vers[i] == NULL)
- continue;
- error = rpc_register(progp->pg_prog, i, proto, port, &dummy);
- if (error < 0)
- break;
- if (port && !dummy) {
- error = -EACCES;
- break;
+ for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+ for (i = 0; i < progp->pg_nvers; i++) {
+ if (progp->pg_vers[i] == NULL)
+ continue;
+ error = rpc_register(progp->pg_prog, i, proto, port, &dummy);
+ if (error < 0)
+ break;
+ if (port && !dummy) {
+ error = -EACCES;
+ break;
+ }
}
}
@@ -264,6 +270,10 @@
u32 dir, prog, vers, proc,
auth_stat, rpc_stat;
int auth_res;
+#ifdef CONFIG_NFSD_SELINUX
+ u32 len, quadlen;
+ char * context;
+#endif
rpc_stat = rpc_success;
@@ -331,6 +341,26 @@
case SVC_COMPLETE:
goto sendit;
}
+
+#ifdef CONFIG_NFSD_SELINUX
+ if (prog == SELINUX_NFS_PROGRAM){
+ rqstp->rq_selinux = 1;
+ len = ntohl(svc_getu32(argv));
+ context = argv->iov_base;
+ quadlen = XDR_QUADLEN(len);
+ if (quadlen > argv->iov_len)
+ goto err_garbage;
+ argv->iov_base = (void*)((u32*)argv->iov_base + quadlen);
+ argv->iov_len -= quadlen*sizeof(u32);
+ if (security_network_context_to_sid(context, len, &rqstp->rq_sid))
+ goto err_garbage;
+ } else {
+ rqstp->rq_selinux = 0;
+ }
+#endif
+ for (progp = serv->sv_program; progp; progp = progp->pg_next)
+ if (prog == progp->pg_prog)
+ break;
if (prog != progp->pg_prog)
goto err_bad_prog;
@@ -365,6 +395,10 @@
if (procp->pc_xdrressize)
svc_reserve(rqstp, procp->pc_xdrressize<<2);
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ security_set_fssid(rqstp->rq_sid);
+#endif
/* Call the function that processes the request. */
if (!versp->vs_dispatch) {
/* Decode arguments */
@@ -390,7 +424,10 @@
goto dropit;
}
}
-
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ security_clear_fssid();
+#endif
/* Check RPC status result */
if (*statp != rpc_success)
resv->iov_len = ((void*)statp) - resv->iov_base + 4;
@@ -408,6 +445,10 @@
return svc_send(rqstp);
dropit:
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ security_clear_fssid();
+#endif
svc_authorise(rqstp); /* doesn't hurt to call this twice */
dprintk("svc: svc_process dropit\n");
svc_drop(rqstp);
@@ -445,9 +486,9 @@
err_bad_prog:
#ifdef RPC_PARANOIA
- if (prog != 100227 || progp->pg_prog != 100003)
- printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
- /* else it is just a Solaris client seeing if ACLs are supported */
+ if (prog != 100227 || serv->sv_program->pg_prog != 100003)
+ printk("svc: unknown program %d\n", prog);
+ /* else it is just a client seeing if ACLs are supported */
#endif
serv->sv_stats->rpcbadfmt++;
svc_putu32(resv, rpc_prog_unavail);
@@ -475,6 +516,10 @@
#ifdef RPC_PARANOIA
printk("svc: failed to decode args\n");
#endif
+#ifdef CONFIG_NFSD_SELINUX
+ if (rqstp->rq_selinux)
+ security_clear_fssid();
+#endif
rpc_stat = rpc_garbage_args;
err_bad:
serv->sv_stats->rpcbadfmt++;
Index: nfs-2.6/security/selinux/Makefile
diff -u nfs-2.6/security/selinux/Makefile:1.1.1.3 nfs-2.6/security/selinux/Makefile:1.6
--- nfs-2.6/security/selinux/Makefile:1.1.1.3 Tue Aug 17 13:54:20 2004
+++ nfs-2.6/security/selinux/Makefile Wed Mar 16 13:17:02 2005
@@ -6,6 +6,10 @@
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
+selinux-$(CONFIG_NFS_SELINUX) += selinux_nfs.o
+
+selinux-$(CONFIG_NFSD_SELINUX) += selinux_nfsd.o
+
selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
EXTRA_CFLAGS += -Isecurity/selinux/include
Index: nfs-2.6/security/selinux/hooks.c
diff -u nfs-2.6/security/selinux/hooks.c:1.1.1.12 nfs-2.6/security/selinux/hooks.c:1.24
--- nfs-2.6/security/selinux/hooks.c:1.1.1.12 Wed Mar 2 10:36:27 2005
+++ nfs-2.6/security/selinux/hooks.c Wed Mar 2 11:00:51 2005
@@ -125,7 +125,7 @@
memset(tsec, 0, sizeof(struct task_security_struct));
tsec->magic = SELINUX_MAGIC;
tsec->task = task;
- tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
+ tsec->fssid = tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
task->security = tsec;
return 0;
@@ -159,7 +159,8 @@
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
if (tsec && tsec->magic == SELINUX_MAGIC)
- isec->task_sid = tsec->sid;
+ isec->task_sid = (tsec->fssid != SECINITSID_UNLABELED) ?
+ tsec->fssid : tsec->sid;
else
isec->task_sid = SECINITSID_UNLABELED;
inode->i_security = isec;
@@ -197,8 +198,13 @@
fsec->magic = SELINUX_MAGIC;
fsec->file = file;
if (tsec && tsec->magic == SELINUX_MAGIC) {
- fsec->sid = tsec->sid;
- fsec->fown_sid = tsec->sid;
+ if (tsec->fssid != SECINITSID_UNLABELED) {
+ fsec->sid = tsec->fssid;
+ fsec->fown_sid = tsec->fssid;
+ } else {
+ fsec->sid = tsec->sid;
+ fsec->fown_sid = tsec->sid;
+ }
} else {
fsec->sid = SECINITSID_UNLABELED;
fsec->fown_sid = SECINITSID_UNLABELED;
@@ -353,6 +359,8 @@
context = d->context;
seen |= Opt_context;
}
+ if (d->flags & NFS_MOUNT_SELINUX)
+ sbsec->behavior = SECURITY_FS_USE_XATTR;
} else
goto out;
@@ -936,6 +944,7 @@
{
struct task_security_struct *tsec;
struct avc_audit_data ad;
+ u32 tsid;
tsec = tsk->security;
@@ -943,7 +952,8 @@
ad.tsk = tsk;
ad.u.cap = cap;
- return avc_has_perm(tsec->sid, tsec->sid,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ return avc_has_perm(tsid, tsid,
SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
}
@@ -970,6 +980,7 @@
struct task_security_struct *tsec;
struct inode_security_struct *isec;
struct avc_audit_data ad;
+ u32 tsid;
tsec = tsk->security;
isec = inode->i_security;
@@ -980,7 +991,8 @@
ad.u.fs.inode = inode;
}
- return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ return avc_has_perm(tsid, isec->sid, isec->sclass, perms, adp);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1018,13 +1030,15 @@
struct inode *inode = dentry->d_inode;
struct avc_audit_data ad;
int rc;
+ u32 tsid;
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.mnt = mnt;
ad.u.fs.dentry = dentry;
- if (tsec->sid != fsec->sid) {
- rc = avc_has_perm(tsec->sid, fsec->sid,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ if (tsid != fsec->sid) {
+ rc = avc_has_perm(tsid, fsec->sid,
SECCLASS_FD,
FD__USE,
&ad);
@@ -1050,6 +1064,7 @@
u32 newsid;
struct avc_audit_data ad;
int rc;
+ u32 tsid;
tsec = current->security;
dsec = dir->i_security;
@@ -1058,7 +1073,8 @@
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
- rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ rc = avc_has_perm(tsid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH,
&ad);
if (rc)
@@ -1067,13 +1083,13 @@
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
- rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
+ rc = security_transition_sid(tsid, dsec->sid, tclass,
&newsid);
if (rc)
return rc;
}
- rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
+ rc = avc_has_perm(tsid, newsid, tclass, FILE__CREATE, &ad);
if (rc)
return rc;
@@ -1095,7 +1111,7 @@
struct task_security_struct *tsec;
struct inode_security_struct *dsec, *isec;
struct avc_audit_data ad;
- u32 av;
+ u32 av, tsid;
int rc;
tsec = current->security;
@@ -1105,9 +1121,10 @@
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
- rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
+ rc = avc_has_perm(tsid, dsec->sid, SECCLASS_DIR, av, &ad);
if (rc)
return rc;
@@ -1126,7 +1143,7 @@
return 0;
}
- rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
+ rc = avc_has_perm(tsid, isec->sid, isec->sclass, av, &ad);
return rc;
}
@@ -1138,7 +1155,7 @@
struct task_security_struct *tsec;
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct avc_audit_data ad;
- u32 av;
+ u32 av, tsid;
int old_is_dir, new_is_dir;
int rc;
@@ -1150,17 +1167,19 @@
AVC_AUDIT_DATA_INIT(&ad, FS);
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
ad.u.fs.dentry = old_dentry;
- rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
+ rc = avc_has_perm(tsid, old_dsec->sid, SECCLASS_DIR,
DIR__REMOVE_NAME | DIR__SEARCH, &ad);
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, old_isec->sid,
+
+ rc = avc_has_perm(tsid, old_isec->sid,
old_isec->sclass, FILE__RENAME, &ad);
if (rc)
return rc;
if (old_is_dir && new_dir != old_dir) {
- rc = avc_has_perm(tsec->sid, old_isec->sid,
+ rc = avc_has_perm(tsid, old_isec->sid,
old_isec->sclass, DIR__REPARENT, &ad);
if (rc)
return rc;
@@ -1170,13 +1189,13 @@
av = DIR__ADD_NAME | DIR__SEARCH;
if (new_dentry->d_inode)
av |= DIR__REMOVE_NAME;
- rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
+ rc = avc_has_perm(tsid, new_dsec->sid, SECCLASS_DIR, av, &ad);
if (rc)
return rc;
if (new_dentry->d_inode) {
new_isec = new_dentry->d_inode->i_security;
new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
- rc = avc_has_perm(tsec->sid, new_isec->sid,
+ rc = avc_has_perm(tsid, new_isec->sid,
new_isec->sclass,
(new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
if (rc)
@@ -1194,10 +1213,12 @@
{
struct task_security_struct *tsec;
struct superblock_security_struct *sbsec;
+ u32 tsid;
tsec = tsk->security;
sbsec = sb->s_security;
- return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ return avc_has_perm(tsid, sbsec->sid, SECCLASS_FILESYSTEM,
perms, ad);
}
@@ -1274,7 +1295,7 @@
struct inode *inode;
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
- u32 newsid;
+ u32 newsid, tsid;
char *context;
unsigned int len;
int rc;
@@ -1296,7 +1317,8 @@
if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
- rc = security_transition_sid(tsec->sid, dsec->sid,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ rc = security_transition_sid(tsid, dsec->sid,
inode_mode_to_security_class(inode->i_mode),
&newsid);
if (rc) {
@@ -2162,7 +2184,7 @@
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec;
struct avc_audit_data ad;
- u32 newsid;
+ u32 newsid, tsid;
int rc = 0;
if (strcmp(name, XATTR_NAME_SELINUX)) {
@@ -2189,7 +2211,8 @@
AVC_AUDIT_DATA_INIT(&ad,FS);
ad.u.fs.dentry = dentry;
- rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
+ tsid = (tsec->fssid != SECINITSID_UNLABELED) ? tsec->fssid : tsec->sid;
+ rc = avc_has_perm(tsid, isec->sid, isec->sclass,
FILE__RELABELFROM, &ad);
if (rc)
return rc;
@@ -2198,7 +2221,7 @@
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
+ rc = avc_has_perm(tsid, newsid, isec->sclass,
FILE__RELABELTO, &ad);
if (rc)
return rc;
Index: nfs-2.6/security/selinux/selinux_nfs.c
diff -u /dev/null nfs-2.6/security/selinux/selinux_nfs.c:1.13
--- /dev/null Mon Jun 20 12:38:59 2005
+++ nfs-2.6/security/selinux/selinux_nfs.c Wed Mar 16 13:17:02 2005
@@ -0,0 +1,93 @@
+/*
+ * NSA Security-Enhanced Linux (SELinux) NFS Related Funtions
+ *
+ * This file contains the SELinux Related Functions for NFS.
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <objsec.h>
+#include <linux/sunrpc/selinux.h>
+#include <linux/sunrpc/xattr.h>
+
+int security_sid_to_network_context(u32 sid, char *context, u32 *len)
+{
+ int rc;
+ char *s = NULL;
+ *len = 0;
+
+ rc = security_sid_to_context(sid, &s, len);
+ if (rc)
+ return rc;
+ memcpy(context, s, *len);
+ kfree(s);
+ return rc;
+}
+
+__u32 security_get_task_sid(void)
+{
+ struct task_security_struct *tsec = current->security;
+
+ return tsec->sid;
+}
+
+int security_revalidate_inode(struct inode *inode)
+{
+ struct inode_security_struct *isec = inode->i_security;
+ u32 sid;
+ struct dentry *dentry;
+ char *context = NULL;
+ unsigned len = NFS_XATTR_SIZE_MAX;
+ int rc = 0;
+
+ if (!inode->i_op->getxattr) {
+ return 0;
+ }
+
+ dentry = d_find_alias(inode);
+ if (!dentry) {
+ printk(KERN_WARNING "%s: no dentry for dev=%s "
+ "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
+ inode->i_ino);
+ return 0;
+ }
+
+ context = kmalloc(len, GFP_KERNEL);
+ if (!context) {
+ dput(dentry);
+ return -ENOMEM;
+ }
+
+ rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
+ context, len);
+ dput(dentry);
+ if (rc < 0) {
+ printk(KERN_WARNING "%s: getxattr returned "
+ "%d for dev=%s ino=%ld\n", __FUNCTION__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+ return rc;
+ }
+
+ rc = security_context_to_sid(context, rc, &sid);
+ if (rc) {
+ printk(KERN_WARNING "%s: context_to_sid(%s) "
+ "returned %d for dev=%s ino=%ld\n",
+ __FUNCTION__, context, -rc,
+ inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+ return rc;
+ }
+ kfree(context);
+ down(&isec->sem);
+ isec->sid = sid;
+ up(&isec->sem);
+
+ return rc;
+}
+
+EXPORT_SYMBOL(security_sid_to_network_context);
+EXPORT_SYMBOL(security_get_task_sid);
+EXPORT_SYMBOL(security_revalidate_inode);
Index: nfs-2.6/security/selinux/selinux_nfsd.c
diff -u /dev/null nfs-2.6/security/selinux/selinux_nfsd.c:1.2
--- /dev/null Mon Jun 20 12:38:59 2005
+++ nfs-2.6/security/selinux/selinux_nfsd.c Fri Mar 18 10:20:43 2005
@@ -0,0 +1,42 @@
+/*
+ * NSA Security-Enhanced Linux (SELinux) NFSD Related Funtions
+ *
+ * This file contains the SELinux Related Functions for NFSD.
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#include <objsec.h>
+
+int security_network_context_to_sid(char *context, u32 len, u32 *sid)
+{
+ return security_context_to_sid(context, len, sid);
+}
+
+void security_set_fssid(u32 sid)
+{
+ struct task_security_struct *tsec = current->security;
+
+ tsec->fssid = sid;
+}
+
+void security_clear_fssid(void)
+{
+ struct task_security_struct *tsec = current->security;
+
+ tsec->fssid = SECINITSID_UNLABELED;
+}
+
+__u32 security_get_inode_sid(struct inode *inode)
+{
+ struct inode_security_struct *isec = inode->i_security;
+
+ return isec->sid;
+}
+
+EXPORT_SYMBOL(security_network_context_to_sid);
+EXPORT_SYMBOL(security_set_fssid);
+EXPORT_SYMBOL(security_clear_fssid);
+EXPORT_SYMBOL(security_get_inode_sid);
Index: nfs-2.6/security/selinux/include/objsec.h
diff -u nfs-2.6/security/selinux/include/objsec.h:1.1.1.7 nfs-2.6/security/selinux/include/objsec.h:1.9
--- nfs-2.6/security/selinux/include/objsec.h:1.1.1.7 Wed Mar 2 10:36:29 2005
+++ nfs-2.6/security/selinux/include/objsec.h Wed Mar 2 11:00:51 2005
@@ -34,6 +34,7 @@
u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */
u32 ptrace_sid; /* SID of ptrace parent */
+ u32 fssid; /* nfs SID */
};
struct inode_security_struct {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment