[PATCH 10/37] Security: Make NFSD work with detached security

2008-02-20 Thread David Howells
Make NFSD work with detached security, using the patches that excise the
security information from task_struct to struct task_security as a base.

Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to
do NFS operations), a task_security record is derived from NFSD's *objective*
security, modified and then applied as the *subjective* security.  This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b)
there is no leakage between two consecutive ops with different security
configurations.

Consideration should probably be given to caching the task_security record on
the basis that there'll probably be several ops that will want to use any
particular security configuration.

Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on
the record pointed to by rec_security so that the disk is accessed
appropriately (see set_security_override[_from_ctx]()).

NOTE!  This patch must be rolled in to one of the earlier security patches to
make it compile fully.

Signed-off-by: David Howells [EMAIL PROTECTED]
---

 fs/nfsd/auth.c|   37 +++-
 fs/nfsd/nfs4recover.c |   64 +++--
 2 files changed, 65 insertions(+), 36 deletions(-)


diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 5586157..ebdc562 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -6,6 +6,7 @@
 
 #include linux/types.h
 #include linux/sched.h
+#include linux/cred.h
 #include linux/sunrpc/svc.h
 #include linux/sunrpc/svcauth.h
 #include linux/nfsd/nfsd.h
@@ -26,12 +27,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export 
*exp)
 
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
-   struct task_security *act_as = current-act_as;
+   struct task_security *sec, *old;
struct svc_cred cred = rqstp-rq_cred;
int i;
int flags = nfsexp_flags(rqstp, exp);
int ret;
 
+   /* derive the new security record from nfsd's objective security */
+   sec = get_kernel_security(current);
+   if (!sec)
+   return -ENOMEM;
+
if (flags  NFSEXP_ALLSQUASH) {
cred.cr_uid = exp-ex_anon_uid;
cred.cr_gid = exp-ex_anon_gid;
@@ -55,26 +61,33 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export 
*exp)
get_group_info(cred.cr_group_info);
 
if (cred.cr_uid != (uid_t) -1)
-   act_as-fsuid = cred.cr_uid;
+   sec-fsuid = cred.cr_uid;
else
-   act_as-fsuid = exp-ex_anon_uid;
+   sec-fsuid = exp-ex_anon_uid;
if (cred.cr_gid != (gid_t) -1)
-   act_as-fsgid = cred.cr_gid;
+   sec-fsgid = cred.cr_gid;
else
-   act_as-fsgid = exp-ex_anon_gid;
+   sec-fsgid = exp-ex_anon_gid;
 
-   if (!cred.cr_group_info)
+   if (!cred.cr_group_info) {
+   put_task_security(sec);
return -ENOMEM;
-   ret = set_groups(act_as, cred.cr_group_info);
+   }
+   ret = set_groups(sec, cred.cr_group_info);
put_group_info(cred.cr_group_info);
if ((cred.cr_uid)) {
-   act_as-cap_effective =
-   cap_drop_nfsd_set(act_as-cap_effective);
+   sec-cap_effective =
+   cap_drop_nfsd_set(sec-cap_effective);
} else {
-   act_as-cap_effective =
-   cap_raise_nfsd_set(act_as-cap_effective,
-  act_as-cap_permitted);
+   sec-cap_effective =
+   cap_raise_nfsd_set(sec-cap_effective,
+  sec-cap_permitted);
}
+
+   /* set the new security as nfsd's subjective security */
+   old = current-act_as;
+   current-act_as = sec;
+   put_task_security(old);
return ret;
 }
 
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index afddc9b..c86aa92 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -46,27 +46,37 @@
 #include linux/scatterlist.h
 #include linux/crypto.h
 #include linux/sched.h
+#include linux/cred.h
 
 #define NFSDDBG_FACILITYNFSDDBG_PROC
 
 /* Globals */
 static struct nameidata rec_dir;
 static int rec_dir_init = 0;
+static struct task_security *rec_security;
 
+/*
+ * switch the special recovery access security in on the current task's
+ * subjective security
+ */
 static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+nfs4_begin_secure(struct task_security **saved_sec)
 {
-   *saveuid = current-act_as-fsuid;
-   *savegid = current-act_as-fsgid;
-   current-act_as-fsuid = 0;
-   current-act_as-fsgid = 0;
+   *saved_sec = current-act_as;
+   current-act_as = get_task_security(rec_security);
 }
 
+/*
+ * return the current task's subjective security to its former glory
+ */
 static void
-nfs4_reset_user(uid_t saveuid, gid_t 

[PATCH 10/37] Security: Make NFSD work with detached security

2008-02-08 Thread David Howells
Make NFSD work with detached security, using the patches that excise the
security information from task_struct to struct task_security as a base.

Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to
do NFS operations), a task_security record is derived from NFSD's *objective*
security, modified and then applied as the *subjective* security.  This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b)
there is no leakage between two consecutive ops with different security
configurations.

Consideration should probably be given to caching the task_security record on
the basis that there'll probably be several ops that will want to use any
particular security configuration.

Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on
the record pointed to by rec_security so that the disk is accessed
appropriately (see set_security_override[_from_ctx]()).

NOTE!  This patch must be rolled in to one of the earlier security patches to
make it compile fully.

Signed-off-by: David Howells [EMAIL PROTECTED]
---

 fs/nfsd/auth.c|   37 +++-
 fs/nfsd/nfs4recover.c |   64 +++--
 2 files changed, 65 insertions(+), 36 deletions(-)


diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 5586157..ebdc562 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -6,6 +6,7 @@
 
 #include linux/types.h
 #include linux/sched.h
+#include linux/cred.h
 #include linux/sunrpc/svc.h
 #include linux/sunrpc/svcauth.h
 #include linux/nfsd/nfsd.h
@@ -26,12 +27,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export 
*exp)
 
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
-   struct task_security *act_as = current-act_as;
+   struct task_security *sec, *old;
struct svc_cred cred = rqstp-rq_cred;
int i;
int flags = nfsexp_flags(rqstp, exp);
int ret;
 
+   /* derive the new security record from nfsd's objective security */
+   sec = get_kernel_security(current);
+   if (!sec)
+   return -ENOMEM;
+
if (flags  NFSEXP_ALLSQUASH) {
cred.cr_uid = exp-ex_anon_uid;
cred.cr_gid = exp-ex_anon_gid;
@@ -55,26 +61,33 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export 
*exp)
get_group_info(cred.cr_group_info);
 
if (cred.cr_uid != (uid_t) -1)
-   act_as-fsuid = cred.cr_uid;
+   sec-fsuid = cred.cr_uid;
else
-   act_as-fsuid = exp-ex_anon_uid;
+   sec-fsuid = exp-ex_anon_uid;
if (cred.cr_gid != (gid_t) -1)
-   act_as-fsgid = cred.cr_gid;
+   sec-fsgid = cred.cr_gid;
else
-   act_as-fsgid = exp-ex_anon_gid;
+   sec-fsgid = exp-ex_anon_gid;
 
-   if (!cred.cr_group_info)
+   if (!cred.cr_group_info) {
+   put_task_security(sec);
return -ENOMEM;
-   ret = set_groups(act_as, cred.cr_group_info);
+   }
+   ret = set_groups(sec, cred.cr_group_info);
put_group_info(cred.cr_group_info);
if ((cred.cr_uid)) {
-   act_as-cap_effective =
-   cap_drop_nfsd_set(act_as-cap_effective);
+   sec-cap_effective =
+   cap_drop_nfsd_set(sec-cap_effective);
} else {
-   act_as-cap_effective =
-   cap_raise_nfsd_set(act_as-cap_effective,
-  act_as-cap_permitted);
+   sec-cap_effective =
+   cap_raise_nfsd_set(sec-cap_effective,
+  sec-cap_permitted);
}
+
+   /* set the new security as nfsd's subjective security */
+   old = current-act_as;
+   current-act_as = sec;
+   put_task_security(old);
return ret;
 }
 
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index bf0217a..ae91262 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -46,27 +46,37 @@
 #include linux/scatterlist.h
 #include linux/crypto.h
 #include linux/sched.h
+#include linux/cred.h
 
 #define NFSDDBG_FACILITYNFSDDBG_PROC
 
 /* Globals */
 static struct nameidata rec_dir;
 static int rec_dir_init = 0;
+static struct task_security *rec_security;
 
+/*
+ * switch the special recovery access security in on the current task's
+ * subjective security
+ */
 static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+nfs4_begin_secure(struct task_security **saved_sec)
 {
-   *saveuid = current-act_as-fsuid;
-   *savegid = current-act_as-fsgid;
-   current-act_as-fsuid = 0;
-   current-act_as-fsgid = 0;
+   *saved_sec = current-act_as;
+   current-act_as = get_task_security(rec_security);
 }
 
+/*
+ * return the current task's subjective security to its former glory
+ */
 static void
-nfs4_reset_user(uid_t saveuid, gid_t