Linux - Fix disk cache access for selinux/AppArmor constrained processes
authorMarc Dionne <marc.c.dionne@gmail.com>
Wed, 28 Oct 2009 21:54:32 +0000 (17:54 -0400)
committerRuss Allbery <rra|account-1000002@unknown>
Wed, 4 Nov 2009 01:47:39 +0000 (17:47 -0800)
Preserve the credentials used for cache initialisation and use then
whenever disk cache files are opened.  This takes advantage of the
credentials separation work from David Howells available in kernels
2.6.29 and above.
Access to cache files was done under the security context of the
user process, causing processes constrained by selinux or AppArmor to
fail to access AFS cache files and causing the cache manager to panic.

Besides the RT tickets, should also fix the following Ubuntu bugs:
 415766 429260 457779 459299

FIXES 92944,125544

Change-Id: Ief8acd65c1a3e4d8c951f80bfd65f8340b8cec34
Reviewed-on: http://gerrit.openafs.org/752
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Reviewed-by: Russ Allbery <rra@stanford.edu>
Tested-by: Russ Allbery <rra@stanford.edu>

src/afs/LINUX/osi_file.c
src/afs/afs_init.c

index 1cb05d2..66ba7cf 100644 (file)
@@ -27,6 +27,9 @@ afs_lock_t afs_xosi;          /* lock is for tvattr */
 extern struct osi_dev cacheDev;
 extern struct vfsmount *afs_cacheMnt;
 extern struct super_block *afs_cacheSBp;
+#if defined(STRUCT_TASK_HAS_CRED)
+extern struct cred *cache_creds;
+#endif
 
 struct file *
 afs_linux_raw_open(afs_dcache_id_t *ainode, ino_t *hint)
@@ -51,7 +54,8 @@ afs_linux_raw_open(afs_dcache_id_t *ainode, ino_t *hint)
     tip->i_flags |= MS_NOATIME;        /* Disable updating access times. */
 
 #if defined(STRUCT_TASK_HAS_CRED)
-    filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR, current_cred());
+    /* Use stashed credentials - prevent selinux/apparmor problems  */
+    filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR, cache_creds);
 #else
     filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR);
 #endif
index 0036107..143d4f8 100644 (file)
@@ -22,6 +22,9 @@
 #include "afsincludes.h"       /* Afs-based standard headers */
 #include "afs/afs_stats.h"     /* afs statistics */
 #include "rx/rxstat.h"
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_HAS_CRED)
+#include <linux/cred.h>
+#endif
 
 #define FSINT_COMMON_XG
 #include "afs/afscbint.h"
@@ -51,6 +54,9 @@ static struct vnode *volumeVnode;
 afs_rwlock_t afs_discon_lock;
 extern afs_rwlock_t afs_disconDirtyLock;
 #endif
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_HAS_CRED)
+const struct cred *cache_creds;
+#endif
 
 /* This is the kernel side of the dynamic vcache setting */
 #ifdef AFS_MAXVCOUNT_ENV
@@ -154,6 +160,16 @@ afs_CacheInit(afs_int32 astatSize, afs_int32 afiles, afs_int32 ablocks,
     afs_cacheStats = astatSize;
     afs_vcacheInit(astatSize);
     afs_dcacheInit(afiles, ablocks, aDentries, achunk, aflags);
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_HAS_CRED)
+    /*
+     * Save current credentials for later access to disk cache files.
+     * If selinux, apparmor or other security modules are enabled,
+     * they might deny access to cache files if the userspace process
+     * is restricted.  Save the credentials used at cache initialisation
+     * for later use when opening cache files.
+     */
+    cache_creds = get_current_cred();
+#endif
 #ifdef AFS_64BIT_CLIENT
 #ifdef AFS_VM_RDWR_ENV
     afs_vmMappingEnd = AFS_CHUNKBASE(0x7fffffff);
@@ -705,6 +721,9 @@ shutdown_cache(void)
        memset(&cacheDev, 0, sizeof(struct osi_dev));
        osi_dnlc_shutdown();
     }
+#if defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_HAS_CRED)
+    put_cred(cache_creds);
+#endif
 }                              /*shutdown_cache */