Whamcloud - gitweb
LU-2675 obd: decruft md_enqueue() and md_intent_lock()
[fs/lustre-release.git] / lustre / llite / file.c
index a9edd6f..2450897 100644 (file)
@@ -45,6 +45,7 @@
 #include <lustre_lite.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
+#include <linux/sched.h>
 #include "llite_internal.h"
 #include <lustre/ll_fiemap.h>
 #include <lustre_ioctl.h>
@@ -3507,8 +3508,14 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
 # endif
 #endif
 {
-        int rc = 0;
-        ENTRY;
+       int rc = 0;
+       struct ll_sb_info *sbi;
+       struct root_squash_info *squash;
+       struct cred *cred = NULL;
+       const struct cred *old_cred = NULL;
+       cfs_cap_t cap;
+       bool squash_id = false;
+       ENTRY;
 
 #ifdef MAY_NOT_BLOCK
        if (mask & MAY_NOT_BLOCK)
@@ -3531,11 +3538,46 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
               PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
 
-       if (ll_i2sbi(inode)->ll_flags & LL_SBI_RMT_CLIENT)
-               return lustre_check_remote_perm(inode, mask);
+       /* squash fsuid/fsgid if needed */
+       sbi = ll_i2sbi(inode);
+       squash = &sbi->ll_squash;
+       if (unlikely(squash->rsi_uid != 0 &&
+                    current_fsuid() == 0 &&
+                    !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) {
+                       squash_id = true;
+       }
+       if (squash_id) {
+               CDEBUG(D_OTHER, "squash creds (%d:%d)=>(%d:%d)\n",
+                      current_fsuid(), current_fsgid(),
+                      squash->rsi_uid, squash->rsi_gid);
+
+               /* update current process's credentials
+                * and FS capability */
+               cred = prepare_creds();
+               if (cred == NULL)
+                       RETURN(-ENOMEM);
 
-       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1);
-       rc = ll_generic_permission(inode, mask, flags, ll_check_acl);
+               cred->fsuid = squash->rsi_uid;
+               cred->fsgid = squash->rsi_gid;
+               for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) {
+                       if ((1 << cap) & CFS_CAP_FS_MASK)
+                               cap_lower(cred->cap_effective, cap);
+               }
+               old_cred = override_creds(cred);
+       }
+
+       ll_stats_ops_tally(sbi, LPROC_LL_INODE_PERM, 1);
+
+       if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
+               rc = lustre_check_remote_perm(inode, mask);
+       else
+               rc = ll_generic_permission(inode, mask, flags, ll_check_acl);
+
+       /* restore current process's credentials and FS capability */
+       if (squash_id) {
+               revert_creds(old_cred);
+               put_cred(cred);
+       }
 
        RETURN(rc);
 }
@@ -3608,15 +3650,15 @@ struct inode_operations ll_file_inode_operations = {
 /* dynamic ioctl number support routins */
 static struct llioc_ctl_data {
        struct rw_semaphore     ioc_sem;
-        cfs_list_t              ioc_head;
+       struct list_head        ioc_head;
 } llioc = {
-        __RWSEM_INITIALIZER(llioc.ioc_sem),
-        CFS_LIST_HEAD_INIT(llioc.ioc_head)
+       __RWSEM_INITIALIZER(llioc.ioc_sem),
+       LIST_HEAD_INIT(llioc.ioc_head)
 };
 
 
 struct llioc_data {
-        cfs_list_t              iocd_list;
+       struct list_head        iocd_list;
         unsigned int            iocd_size;
         llioc_callback_t        iocd_cb;
         unsigned int            iocd_count;
@@ -3645,7 +3687,7 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd)
         memcpy(in_data->iocd_cmd, cmd, sizeof(unsigned int) * count);
 
        down_write(&llioc.ioc_sem);
-        cfs_list_add_tail(&in_data->iocd_list, &llioc.ioc_head);
+       list_add_tail(&in_data->iocd_list, &llioc.ioc_head);
        up_write(&llioc.ioc_sem);
 
         RETURN(in_data);
@@ -3659,11 +3701,11 @@ void ll_iocontrol_unregister(void *magic)
                 return;
 
        down_write(&llioc.ioc_sem);
-        cfs_list_for_each_entry(tmp, &llioc.ioc_head, iocd_list) {
+       list_for_each_entry(tmp, &llioc.ioc_head, iocd_list) {
                 if (tmp == magic) {
                         unsigned int size = tmp->iocd_size;
 
-                        cfs_list_del(&tmp->iocd_list);
+                       list_del(&tmp->iocd_list);
                        up_write(&llioc.ioc_sem);
 
                         OBD_FREE(tmp, size);
@@ -3687,7 +3729,7 @@ ll_iocontrol_call(struct inode *inode, struct file *file,
         int rc = -EINVAL, i;
 
        down_read(&llioc.ioc_sem);
-        cfs_list_for_each_entry(data, &llioc.ioc_head, iocd_list) {
+       list_for_each_entry(data, &llioc.ioc_head, iocd_list) {
                 for (i = 0; i < data->iocd_count; i++) {
                         if (cmd != data->iocd_cmd[i])
                                 continue;