Whamcloud - gitweb
land b_hd_sec: perm/acl authorization for remote users.
authorericm <ericm>
Wed, 13 Jul 2005 00:59:04 +0000 (00:59 +0000)
committerericm <ericm>
Wed, 13 Jul 2005 00:59:04 +0000 (00:59 +0000)
25 files changed:
lustre/include/linux/lustre_idl.h
lustre/include/linux/lustre_lite.h
lustre/include/linux/obd.h
lustre/include/linux/obd_class.h
lustre/include/linux/obd_support.h
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/namei.c
lustre/lmv/lmv_obd.c
lustre/lov/lov_obd.c
lustre/mdc/mdc_request.c
lustre/mds/handler.c
lustre/mds/mds_internal.h
lustre/mds/mds_lib.c
lustre/mds/mds_open.c
lustre/obdclass/lprocfs_status.c
lustre/ptlrpc/lproc_ptlrpc.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/ptlrpc_module.c
lustre/sec/gss/sec_gss.c
lustre/sec/gss/svcsec_gss.c
lustre/sec/sec.c
lustre/sec/sec_null.c
lustre/utils/wirecheck.c

index 5441eb7..a20a8a0 100644 (file)
@@ -415,7 +415,8 @@ struct lov_mds_md_v0 {            /* LOV EA mds/wire data (little-endian) */
 #define OBD_MD_FID      (0x0000000080000000LL)    /* lustre_id data */
 #define OBD_MD_MEA      (0x0000000100000000LL)    /* shows we are interested in MEA */
 #define OBD_MD_FLEALIST (0x0000000200000000LL)    /* list extended attributes */
-#define OBD_MD_FLACL_ACCESS (0x0000000400000000LL) /*access acl*/
+#define OBD_MD_FLACL_ACCESS (0x0000000400000000LL) /* access acl */
+#define OBD_MD_RACL     (0x0000000800000000LL)    /* remote acl */
 
 #define OBD_MD_FLNOTOBD (~(OBD_MD_FLBLOCKS | OBD_MD_LINKNAME |          \
                            OBD_MD_FLEASIZE | OBD_MD_FLHANDLE |          \
@@ -554,6 +555,7 @@ typedef enum {
         MDS_UNPIN        = 43,
         MDS_SYNC         = 44,
         MDS_DONE_WRITING = 45,
+        MDS_ACCESS_CHECK = 46,
         MDS_LAST_OPC
 } mds_cmd_t;
 
@@ -668,13 +670,24 @@ struct mds_body {
 
 extern void lustre_swab_mds_body (struct mds_body *b);
 
+struct mds_remote_perm {
+        __u32           mrp_auth_uid;
+        __u32           mrp_auth_gid;
+        __u16           mrp_perm;
+        __u8            mrp_allow_setuid;
+        __u8            mrp_allow_setgid;
+};
+
 struct lustre_md {
-        struct mds_body *body;
-        struct lov_stripe_md *lsm;
-        struct mea *mea;
-        struct posix_acl *acl_access;
+        struct mds_body        *body;
+        struct lov_stripe_md   *lsm;
+        struct mea             *mea;
+        struct posix_acl       *posix_acl;
+        struct mds_remote_perm *remote_perm;
 };
 
+void lustre_swab_remote_perm(struct mds_remote_perm *p);
+
 struct mdc_op_data {
         struct lustre_id id1;
         struct lustre_id id2;
index afa7475..2276cec 100644 (file)
@@ -39,6 +39,9 @@
 #include <linux/namei.h>
 
 
+/* forward declarations */
+struct remote_acl;
+
 /* careful, this is easy to screw up */
 #define PAGE_CACHE_MAXBYTES ((__u64)(~0UL) << PAGE_CACHE_SHIFT)
 
@@ -110,7 +113,9 @@ struct ll_inode_info {
         __u64                   lli_open_fd_write_count;
         struct obd_client_handle *lli_mds_exec_och;
         __u64                   lli_open_fd_exec_count;
-        struct posix_acl       *lli_acl_access;
+
+        struct posix_acl       *lli_posix_acl;
+        struct remote_acl      *lli_remote_acl;
 };
 
 // FIXME: replace the name of this with LL_I to conform to kernel stuff
index deca7ec..ff20fe3 100644 (file)
@@ -903,6 +903,8 @@ struct md_ops {
         int (*m_getattr)(struct obd_export *, struct lustre_id *,
                          __u64, const char *, int,
                          unsigned int, struct ptlrpc_request **);
+        int (*m_access_check)(struct obd_export *, struct lustre_id *,
+                              struct ptlrpc_request **);
         int (*m_getattr_lock)(struct obd_export *, struct lustre_id *,
                               char *, int, __u64,
                               unsigned int, struct ptlrpc_request **);
index 6554d4f..03c9567 100644 (file)
@@ -1190,6 +1190,17 @@ static inline int md_getattr(struct obd_export *exp, struct lustre_id *id,
         RETURN(rc);
 }
 
+static inline int md_access_check(struct obd_export *exp, struct lustre_id *id,
+                                  struct ptlrpc_request **request)
+{
+        int rc;
+        ENTRY;
+        EXP_CHECK_MD_OP(exp, access_check);
+        MD_COUNTER_INCREMENT(exp->exp_obd, access_check);
+        rc = MDP(exp->exp_obd, access_check)(exp, id, request);
+        RETURN(rc);
+}
+
 static inline int md_change_cbdata(struct obd_export *exp, struct lustre_id *id,
                                    ldlm_iterator_t it, void *data)
 {
index f6508c0..a7ec412 100644 (file)
@@ -89,6 +89,8 @@ extern wait_queue_head_t obd_race_waitq;
 #define OBD_FAIL_MDS_PAUSE_OPEN          0x129
 #define OBD_FAIL_MDS_STATFS_LCW_SLEEP    0x12a
 #define OBD_FAIL_MDS_OPEN_CREATE         0x12b
+#define OBD_FAIL_MDS_ACCESS_CHECK_NET    0x12c
+#define OBD_FAIL_MDS_ACCESS_CHECK_PACK   0x12d
 
 #define OBD_FAIL_OST                     0x200
 #define OBD_FAIL_OST_CONNECT_NET         0x201
index 6fc869f..54233fc 100644 (file)
@@ -1859,9 +1859,9 @@ int ll_setxattr(struct dentry *dentry, const char *name, const void *value,
                                         
                 lli = ll_i2info(dentry->d_inode);
                 spin_lock(&lli->lli_lock);
-                if (lli->lli_acl_access != NULL)
-                        posix_acl_release(lli->lli_acl_access);
-                lli->lli_acl_access = acl;
+                if (lli->lli_posix_acl != NULL)
+                        posix_acl_release(lli->lli_posix_acl);
+                lli->lli_posix_acl = acl;
                 spin_unlock(&lli->lli_lock);
         }
         EXIT;
@@ -1947,7 +1947,7 @@ lustre_check_acl(struct inode *inode, int mask)
         struct ptlrpc_request *req = NULL;
         struct ll_inode_info *lli = ll_i2info(inode);
         struct posix_acl *acl;
-        int rc;
+        int rc = 0;
         ENTRY;
 
         sbi = ll_i2sbi(inode);
@@ -1969,18 +1969,23 @@ lustre_check_acl(struct inode *inode, int mask)
                 GOTO(out, rc);
         }
 
-        ll_lookup_finish_locks(&it, &de);
-        ll_intent_free(&it);
-
-        spin_lock(&lli->lli_lock);
-        acl = posix_acl_dup(ll_i2info(inode)->lli_acl_access);
-        spin_unlock(&lli->lli_lock);
+        if (sbi->ll_remote) {
+                rc = ll_remote_acl_permission(inode, mask);
+        } else {
+                spin_lock(&lli->lli_lock);
+                acl = posix_acl_dup(ll_i2info(inode)->lli_posix_acl);
+                spin_unlock(&lli->lli_lock);
 
-        if (!acl)
-                GOTO(out, rc = -EAGAIN);
+                if (!acl)
+                        rc = -EAGAIN;
+                else {
+                        rc = posix_acl_permission(inode, acl, mask);
+                        posix_acl_release(acl);
+                }
+        }
 
-        rc = posix_acl_permission(inode, acl, mask);
-        posix_acl_release(acl);
+        ll_lookup_finish_locks(&it, &de);
+        ll_intent_free(&it);
 
 out:
         if (req)
index eaef944..363df56 100644 (file)
@@ -196,6 +196,39 @@ enum {
         LLAP__ORIGIN_MAX,
 };
 
+/*
+ * remote ACL stuff
+ */
+#define REMOTE_ACL_HASHSIZE     16
+
+struct remote_acl {
+        struct list_head        ra_perm_cache[REMOTE_ACL_HASHSIZE];
+        spinlock_t              ra_lock;
+        /* we use one sem per inode, it's kind of coarse: one user must
+         * wait if another user is updating the perm on this inode. but
+         * I guess this is fine is real world usage.
+         */
+        struct semaphore        ra_update_sem;
+};
+
+struct lustre_remote_perm {
+        struct list_head        lrp_list;
+        uid_t                   lrp_auth_uid;       /* authenticated uid */
+        gid_t                   lrp_auth_gid;       /* authenticated gid */
+        uint16_t                lrp_perm;           /* permission bits */
+        uint16_t                lrp_valid:1,        /* lrp_perm is valid */
+                                lrp_setuid:1,       /* allow setuid */
+                                lrp_setgid:1;       /* allow setgid */
+        struct list_head        lrp_setxid_perms;   /* setxid perms list */
+};
+
+struct remote_perm_setxid {
+        struct list_head        list; /* permission list */
+        uid_t                   uid;
+        gid_t                   gid;
+        uint16_t                perm;
+};
+
 /* llite/lproc_llite.c */
 int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
                                 struct super_block *sb, char *lov,
@@ -316,6 +349,8 @@ int ll_statfs(struct super_block *sb, struct kstatfs *sfs);
 int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
                        unsigned long maxage);
 void ll_update_inode(struct inode *inode, struct lustre_md *);
+int ll_fetch_remote_perm(struct inode *inode, struct ptlrpc_request *req,
+                         uint16_t *perm);
 int it_disposition(struct lookup_intent *it, int flag);
 void it_set_disposition(struct lookup_intent *it, int flag);
 void ll_read_inode2(struct inode *inode, void *opaque);
@@ -334,6 +369,10 @@ int ll_process_config_update(struct ll_sb_info *sbi, int clean);
 int ll_show_options(struct seq_file *m, struct vfsmount *mnt);
 int ll_flush_cred(struct inode *inode);
 
+int ll_remote_acl_permission(struct inode *inode, int mode);
+int ll_remote_acl_update(struct inode *inode, struct mds_remote_perm *perm);
+void ll_inode_invalidate_acl(struct inode *inode);
+
 /* llite/special.c */
 extern struct inode_operations ll_special_inode_operations;
 extern struct file_operations ll_special_chr_inode_fops;
index 84f3263..97cf2e8 100644 (file)
@@ -1008,6 +1008,8 @@ int null_if_equal(struct ldlm_lock *lock, void *data)
         return LDLM_ITER_CONTINUE;
 }
 
+static void remote_acl_free(struct remote_acl *racl);
+
 void ll_clear_inode(struct inode *inode)
 {
         struct lustre_id id;
@@ -1053,6 +1055,19 @@ void ll_clear_inode(struct inode *inode)
                          strlen(lli->lli_symlink_name) + 1);
                 lli->lli_symlink_name = NULL;
         }
+
+        if (lli->lli_posix_acl) {
+                LASSERT(lli->lli_remote_acl == NULL);
+                posix_acl_release(lli->lli_posix_acl);
+                lli->lli_posix_acl = NULL;
+        }
+
+        if (lli->lli_remote_acl) {
+                LASSERT(lli->lli_posix_acl == NULL);
+                remote_acl_free(lli->lli_remote_acl);
+                lli->lli_remote_acl = NULL;
+        }
+
         lli->lli_inode_magic = LLI_INODE_DEAD;
 
         EXIT;
@@ -1363,13 +1378,419 @@ int ll_statfs(struct super_block *sb, struct kstatfs *sfs)
         return 0;
 }
 
+
+/********************************
+ * remote acl                   *
+ ********************************/
+
+static struct remote_acl *remote_acl_alloc(void)
+{
+        struct remote_acl *racl;
+        int i;
+
+        OBD_ALLOC(racl, sizeof(*racl));
+        if (!racl)
+                return NULL;
+
+        spin_lock_init(&racl->ra_lock);
+        init_MUTEX(&racl->ra_update_sem);
+
+        for (i = 0; i < REMOTE_ACL_HASHSIZE; i++)
+                INIT_LIST_HEAD(&racl->ra_perm_cache[i]);
+
+        return racl;
+}
+
+/*
+ * caller should guarantee no race here.
+ */
+static void remote_perm_flush_xperms(struct lustre_remote_perm *perm)
+{
+        struct remote_perm_setxid *xperm;
+
+        while (!list_empty(&perm->lrp_setxid_perms)) {
+                xperm = list_entry(perm->lrp_setxid_perms.next,
+                                   struct remote_perm_setxid,
+                                   list);
+                list_del(&xperm->list);
+                OBD_FREE(xperm, sizeof(*xperm));
+        }
+}
+
+/*
+ * caller should guarantee no race here.
+ */
+static void remote_acl_flush(struct remote_acl *racl)
+{
+        struct list_head *head;
+        struct lustre_remote_perm *perm, *tmp;
+        int i;
+
+        for (i = 0; i < REMOTE_ACL_HASHSIZE; i++) {
+                head = &racl->ra_perm_cache[i];
+
+                list_for_each_entry_safe(perm, tmp, head, lrp_list) {
+                        remote_perm_flush_xperms(perm);
+                        list_del(&perm->lrp_list);
+                        OBD_FREE(perm, sizeof(*perm));
+                }
+        }
+}
+
+static void remote_acl_free(struct remote_acl *racl)
+{
+        if (!racl)
+                return;
+
+        down(&racl->ra_update_sem);
+        spin_lock(&racl->ra_lock);
+        remote_acl_flush(racl);
+        spin_unlock(&racl->ra_lock);
+        up(&racl->ra_update_sem);
+
+        OBD_FREE(racl, sizeof(*racl));
+}
+
+static inline int remote_acl_hashfunc(__u32 id)
+{
+        return (id & (REMOTE_ACL_HASHSIZE - 1));
+}
+
+static
+int __remote_acl_check(struct remote_acl *racl, unsigned int *perm)
+{
+        struct list_head *head;
+        struct lustre_remote_perm *lperm;
+        struct remote_perm_setxid *xperm;
+        int found = 0, rc = -ENOENT;
+
+        LASSERT(racl);
+        head = &racl->ra_perm_cache[remote_acl_hashfunc(current->uid)];
+        spin_lock(&racl->ra_lock);
+
+        list_for_each_entry(lperm, head, lrp_list) {
+                if (lperm->lrp_auth_uid == current->uid) {
+                        found = 1;
+                        break;
+                }
+        }
+
+        if (!found)
+                goto out;
+
+        if (lperm->lrp_auth_uid == current->fsuid &&
+            lperm->lrp_auth_gid == current->fsgid) {
+                if (lperm->lrp_valid) {
+                        *perm = lperm->lrp_perm;
+                        rc = 0;
+                }
+                goto out;
+        } else if ((!lperm->lrp_setuid &&
+                    lperm->lrp_auth_uid != current->fsuid) ||
+                   (!lperm->lrp_setgid &&
+                    lperm->lrp_auth_gid != current->fsgid))  {
+                *perm = 0;
+                rc = 0;
+                goto out;
+        }
+
+        list_for_each_entry(xperm, &lperm->lrp_setxid_perms, list) {
+                if (xperm->uid == current->fsuid &&
+                    xperm->gid == current->fsgid) {
+                        *perm = xperm->perm;
+                        rc = 0;
+                        goto out;
+                }
+        }
+
+out:
+        spin_unlock(&racl->ra_lock);
+        return rc;
+}
+
+static
+int __remote_acl_update(struct remote_acl *racl,
+                        struct mds_remote_perm *mperm,
+                        struct lustre_remote_perm *lperm,
+                        struct remote_perm_setxid *xperm)
+{
+        struct list_head *head;
+        struct lustre_remote_perm *lp;
+        struct remote_perm_setxid *xp;
+        int found = 0, setuid = 0, setgid = 0;
+
+        LASSERT(racl);
+        LASSERT(mperm);
+        LASSERT(lperm);
+        LASSERT(current->uid == mperm->mrp_auth_uid);
+
+        if (current->fsuid != mperm->mrp_auth_uid)
+                setuid = 1;
+        if (current->fsgid != mperm->mrp_auth_gid)
+                setgid = 1;
+
+        head = &racl->ra_perm_cache[remote_acl_hashfunc(current->uid)];
+        spin_lock(&racl->ra_lock);
+
+        list_for_each_entry(lp, head, lrp_list) {
+                if (lp->lrp_auth_uid == current->uid) {
+                        found = 1;
+                        break;
+                }
+        }
+
+        if (found) {
+                OBD_FREE(lperm, sizeof(*lperm));
+
+                if (!lp->lrp_valid && !setuid && !setgid) {
+                        lp->lrp_perm = mperm->mrp_perm;
+                        lp->lrp_valid = 1;
+                }
+
+                /* sanity check for changes of setxid rules */
+                if ((lp->lrp_setuid != 0) != (mperm->mrp_allow_setuid != 0)) {
+                        CWARN("setuid changes: %d => %d\n",
+                              (lp->lrp_setuid != 0),
+                              (mperm->mrp_allow_setuid != 0));
+                        lp->lrp_setuid = (mperm->mrp_allow_setuid != 0);
+                }
+
+                if ((lp->lrp_setgid != 0) != (mperm->mrp_allow_setgid != 0)) {
+                        CWARN("setgid changes: %d => %d\n",
+                              (lp->lrp_setgid != 0),
+                              (mperm->mrp_allow_setgid != 0));
+                        lp->lrp_setgid = (mperm->mrp_allow_setgid != 0);
+                }
+
+                if (!lp->lrp_setuid && !lp->lrp_setgid &&
+                    !list_empty(&lp->lrp_setxid_perms)) {
+                        remote_perm_flush_xperms(lp);
+                }
+        } else {
+                /* initialize lperm and linked into hashtable
+                 */
+                INIT_LIST_HEAD(&lperm->lrp_setxid_perms);
+                lperm->lrp_auth_uid = mperm->mrp_auth_uid;
+                lperm->lrp_auth_gid = mperm->mrp_auth_gid;
+                lperm->lrp_setuid = (mperm->mrp_allow_setuid != 0);
+                lperm->lrp_setgid = (mperm->mrp_allow_setgid != 0);
+                list_add(&lperm->lrp_list, head);
+
+                if (!setuid && !setgid) {
+                        /* in this case, i'm the authenticated user,
+                         * and mrp_perm is for me.
+                         */
+                        lperm->lrp_perm = mperm->mrp_perm;
+                        lperm->lrp_valid = 1;
+                        spin_unlock(&racl->ra_lock);
+
+                        if (xperm)
+                                OBD_FREE(xperm, sizeof(*xperm));
+                        return 0;
+                }
+
+                lp = lperm;
+                /* fall through */
+        }
+
+        LASSERT(lp->lrp_setuid || lp->lrp_setgid ||
+                list_empty(&lp->lrp_setxid_perms));
+
+        /* if no xperm supplied, we are all done here */
+        if (!xperm) {
+                spin_unlock(&racl->ra_lock);
+                return 0;
+        }
+
+        /* whether we allow setuid/setgid */
+        if ((!lp->lrp_setuid && setuid) || (!lp->lrp_setgid && setgid)) {
+                OBD_FREE(xperm, sizeof(*xperm));
+                spin_unlock(&racl->ra_lock);
+                return 0;
+        }
+
+        /* traverse xperm list */
+        list_for_each_entry(xp, &lp->lrp_setxid_perms, list) {
+                if (xp->uid == current->fsuid &&
+                    xp->gid == current->fsgid) {
+                        if (xp->perm != mperm->mrp_perm) {
+                                /* actually this should not happen */
+                                CWARN("perm changed: %o => %o\n",
+                                      xp->perm, mperm->mrp_perm);
+                                xp->perm = mperm->mrp_perm;
+                        }
+                        OBD_FREE(xperm, sizeof(*xperm));
+                        spin_unlock(&racl->ra_lock);
+                        return 0;
+                }
+        }
+
+        /* finally insert this xperm */
+        xperm->uid = current->fsuid;
+        xperm->gid = current->fsgid;
+        xperm->perm = mperm->mrp_perm;
+        list_add(&xperm->list, &lp->lrp_setxid_perms);
+
+        spin_unlock(&racl->ra_lock);
+        return 0;
+}
+
+/*
+ * remote_acl semaphore must be held by caller
+ */
+static
+int remote_acl_update_locked(struct remote_acl *racl,
+                             struct mds_remote_perm *mperm)
+{
+        struct lustre_remote_perm *lperm;
+        struct remote_perm_setxid *xperm;
+        int setuid = 0, setgid = 0;
+
+        might_sleep();
+
+        if (current->uid != mperm->mrp_auth_uid) {
+                CERROR("current uid %u while authenticated as %u\n",
+                       current->uid, mperm->mrp_auth_uid);
+                return -EINVAL;
+        }
+
+        if (current->fsuid != mperm->mrp_auth_uid)
+                setuid = 1;
+        if (current->fsgid == mperm->mrp_auth_gid)
+                setgid = 1;
+
+        OBD_ALLOC(lperm, sizeof(*lperm));
+        if (!lperm)
+                return -ENOMEM;
+
+        if ((setuid || setgid) &&
+            !(setuid && !mperm->mrp_allow_setuid) &&
+            !(setgid && !mperm->mrp_allow_setgid)) {
+                OBD_ALLOC(xperm, sizeof(*xperm));
+                if (!xperm) {
+                        OBD_FREE(lperm, sizeof(*lperm));
+                        return -ENOMEM;
+                }
+        } else
+                xperm = NULL;
+
+        return __remote_acl_update(racl, mperm, lperm, xperm);
+}
+
+/*
+ * return -EACCES at any error cases
+ */
+int ll_remote_acl_permission(struct inode *inode, int mode)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct remote_acl *racl = ll_i2info(inode)->lli_remote_acl;
+        struct ptlrpc_request *req = NULL;
+        struct lustre_id id;
+        struct mds_remote_perm *mperm;
+        int rc = -EACCES, perm;
+
+        if (!racl)
+                return -EACCES;
+
+        if (__remote_acl_check(racl, &perm) == 0) {
+                return ((perm & mode) == mode ? 0 : -EACCES);
+        }
+
+        might_sleep();
+
+        /* doing update
+         */
+        down(&racl->ra_update_sem);
+
+        /* we might lose the race when obtain semaphore,
+         * so check again.
+         */
+        if (__remote_acl_check(racl, &perm) == 0) {
+                if ((perm & mode) == mode)
+                        rc = 0;
+                goto out;
+        }
+
+        /* really fetch from mds
+         */
+        ll_inode2id(&id, inode);
+        if (md_access_check(sbi->ll_md_exp, &id, &req))
+                goto out;
+
+        /* status non-zero indicate there's more apparent error
+         * detected by mds, e.g. didn't allow this user at all.
+         * we simply ignore and didn't cache it.
+         */
+        if (req->rq_repmsg->status)
+                goto out;
+
+        mperm = lustre_swab_repbuf(req, 1, sizeof(*mperm),
+                                   lustre_swab_remote_perm);
+        LASSERT(mperm);
+        LASSERT_REPSWABBED(req, 1);
+
+        if ((mperm->mrp_perm & mode) == mode)
+                rc = 0;
+
+        remote_acl_update_locked(racl, mperm);
+out:
+        if (req)
+                ptlrpc_req_finished(req);
+
+        up(&racl->ra_update_sem);
+        return rc;
+}
+
+int ll_remote_acl_update(struct inode *inode, struct mds_remote_perm *perm)
+{
+        struct remote_acl *racl = ll_i2info(inode)->lli_remote_acl;
+        int rc;
+
+        LASSERT(perm);
+
+        if (!racl)
+                return -EACCES;
+
+        down(&racl->ra_update_sem);
+        rc = remote_acl_update_locked(racl, perm);
+        up(&racl->ra_update_sem);
+
+        return rc;
+}
+
+void ll_inode_invalidate_acl(struct inode *inode)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct ll_inode_info *lli = ll_i2info(inode);
+
+        if (sbi->ll_remote) {
+                struct remote_acl *racl = lli->lli_remote_acl;
+
+                LASSERT(!lli->lli_posix_acl);
+                if (racl) {
+                        down(&racl->ra_update_sem);
+                        spin_lock(&racl->ra_lock);
+                        remote_acl_flush(lli->lli_remote_acl);
+                        spin_unlock(&racl->ra_lock);
+                        up(&racl->ra_update_sem);
+                }
+        } else {
+                LASSERT(!lli->lli_remote_acl);
+                spin_lock(&lli->lli_lock);
+                posix_acl_release(lli->lli_posix_acl);
+                lli->lli_posix_acl = NULL;
+                spin_unlock(&lli->lli_lock);
+        }
+}
+
 void ll_update_inode(struct inode *inode, struct lustre_md *md)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
         struct lov_stripe_md *lsm = md->lsm;
         struct mds_body *body = md->body;
         struct mea *mea = md->mea;
-        struct posix_acl *ll_acl_access = md->acl_access;
+        struct posix_acl *posix_acl = md->posix_acl;
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
         ENTRY;
 
         LASSERT((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
@@ -1441,14 +1862,25 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
        if (body->valid & OBD_MD_FLGENER)
                id_gen(&lli->lli_id) = id_gen(&body->id1);
 
-        spin_lock(&lli->lli_lock);
-        if (ll_acl_access != NULL) {
-                if (lli->lli_acl_access != NULL)
-                        posix_acl_release(lli->lli_acl_access);
-                lli->lli_acl_access = ll_acl_access;
+        /* local/remote ACL */
+        if (sbi->ll_remote) {
+                LASSERT(md->posix_acl == NULL);
+                if (md->remote_perm) {
+                        ll_remote_acl_update(inode, md->remote_perm);
+                        OBD_FREE(md->remote_perm, sizeof(*md->remote_perm));
+                        md->remote_perm = NULL;
+                }
+        } else {
+                LASSERT(md->remote_perm == NULL);
+                spin_lock(&lli->lli_lock);
+                if (posix_acl != NULL) {
+                        if (lli->lli_posix_acl != NULL)
+                                posix_acl_release(lli->lli_posix_acl);
+                        lli->lli_posix_acl = posix_acl;
+                }
+                spin_unlock(&lli->lli_lock);
         }
-        spin_unlock(&lli->lli_lock);
+
         if (body->valid & OBD_MD_FLID)
                 inode->i_ino = id_ino(&body->id1);
         if (body->valid & OBD_MD_FLGENER)
@@ -1520,6 +1952,11 @@ void ll_read_inode2(struct inode *inode, void *opaque)
 
         LASSERT(!lli->lli_smd);
 
+        if (ll_i2sbi(inode)->ll_remote) {
+                lli->lli_remote_acl = remote_acl_alloc();
+                /* if failed alloc, nobody will be able to access this inode */
+        }
+
         /* Core attributes from the MDS first.  This is a new inode, and
          * the VFS doesn't zero times in the core inode so we have to do
          * it ourselves.  They will be overwritten by either MDS or OST
index a0c8916..9cad4e7 100644 (file)
@@ -221,6 +221,15 @@ int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                         truncate_inode_pages(inode->i_mapping, 0);
                 }
 
+                /* we can't invalide acl here: suppose we touch a new file
+                 * under a dir, blocking ast on dir will lead to open failure
+                 * on client, although succeed on mds. it's kind of weird,
+                 * the real fix i think is improve client-vfs interaction.
+                 */
+#if 0
+                ll_inode_invalidate_acl(inode);
+#endif
+
                 if (inode->i_sb->s_root &&
                     inode != inode->i_sb->s_root->d_inode &&
                     (bits & MDS_INODELOCK_LOOKUP))
index 86f3035..e21076e 100644 (file)
@@ -752,6 +752,24 @@ static int lmv_getattr(struct obd_export *exp, struct lustre_id *id,
         RETURN(rc);
 }
 
+static int lmv_access_check(struct obd_export *exp,
+                            struct lustre_id *id,
+                            struct ptlrpc_request **request)
+{
+        struct obd_device *obd = exp->exp_obd;
+        struct lmv_obd *lmv = &obd->u.lmv;
+        int rc, i = id_group(id);
+        ENTRY;
+
+        rc = lmv_check_connect(obd);
+        if (rc)
+                RETURN(rc);
+
+        LASSERT(i < lmv->desc.ld_tgt_count);
+        rc = md_access_check(lmv->tgts[i].ltd_exp, id, request);
+        RETURN(rc);
+}
+
 static int lmv_change_cbdata(struct obd_export *exp,
                              struct lustre_id *id, 
                              ldlm_iterator_t it,
@@ -2198,6 +2216,7 @@ struct md_ops lmv_md_ops = {
         .m_get_real_obd        = lmv_get_real_obd,
         .m_valid_attrs         = lmv_valid_attrs,
         .m_delete_inode        = lmv_delete_inode,
+        .m_access_check        = lmv_access_check,
 };
 
 int __init lmv_init(void)
index 891c132..f429eba 100644 (file)
@@ -2000,7 +2000,6 @@ static int lov_get_info(struct obd_export *exp, __u32 keylen,
                 }
                 LDLM_ERROR(data->lock, "lock on inode without such object\n");
                 dump_lsm(D_ERROR, data->lsm);
-                portals_debug_dumpstack(NULL);
                 RETURN(-ENXIO);
         } else if (keylen >= strlen("size_to_stripe") &&
                    strcmp(key, "size_to_stripe") == 0) {
index fc4dc6d..666782e 100644 (file)
@@ -223,6 +223,47 @@ int mdc_getattr(struct obd_export *exp, struct lustre_id *id,
         RETURN (rc);
 }
 
+int mdc_access_check(struct obd_export *exp, struct lustre_id *id,
+                     struct ptlrpc_request **request)
+
+{
+        struct ptlrpc_request *req;
+        struct mds_body *body;
+        int size[2] = {0, sizeof(*body)};
+        int rc;
+        ENTRY;
+
+        size[0] = lustre_secdesc_size();
+        req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MDS_VERSION,
+                              MDS_ACCESS_CHECK, 2, size, NULL);
+        if (!req)
+                GOTO(out, rc = -ENOMEM);
+
+        lustre_pack_secdesc(req, size[0]);
+        body = lustre_msg_buf(req->rq_reqmsg, MDS_REQ_REC_OFF, sizeof (*body));
+        memcpy(&body->id1, id, sizeof(*id));
+
+        req->rq_replen = lustre_msg_size(2, size);
+        mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
+        rc = ptlrpc_queue_wait(req);
+        mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
+        if (rc != 0) {
+                ptlrpc_req_finished (req);
+                req = NULL;
+        } else {
+                body = lustre_swab_repbuf (req, 0, sizeof (*body),
+                                           lustre_swab_mds_body);
+                if (body == NULL) {
+                        CERROR ("Can't unpack mds_body\n");
+                        RETURN (-EPROTO);
+                }
+        }
+
+ out:
+        *request = req;
+        RETURN (rc);
+}
+
 int mdc_getattr_lock(struct obd_export *exp, struct lustre_id *id,
                      char *filename, int namelen, __u64 valid,
                      unsigned int ea_size, struct ptlrpc_request **request)
@@ -287,11 +328,12 @@ int mdc_req2lustre_md(struct obd_export *exp_lmv, struct ptlrpc_request *req,
                       unsigned int offset, struct obd_export *exp_lov, 
                       struct lustre_md *md)
 {
+        struct lov_mds_md *lmm;
+        struct posix_acl *acl;
+        struct mds_remote_perm *perm;
         void *buf;
-        int rc = 0;
         int size, acl_off;
-        struct posix_acl *acl;
-        struct lov_mds_md *lmm;
+        int rc = 0;
         ENTRY;
 
         LASSERT(md != NULL);
@@ -304,7 +346,7 @@ int mdc_req2lustre_md(struct obd_export *exp_lmv, struct ptlrpc_request *req,
 
         LASSERT_REPSWABBED(req, offset);
 
-        if (!(md->body->valid & OBD_MD_FLEASIZE) && 
+        if (!(md->body->valid & OBD_MD_FLEASIZE) &&
             !(md->body->valid & OBD_MD_FLDIREA))
                 RETURN(0);
 
@@ -355,30 +397,54 @@ int mdc_req2lustre_md(struct obd_export *exp_lmv, struct ptlrpc_request *req,
                         S_ISSOCK(md->body->mode));
         }
 
-        acl_off = (md->body->valid & OBD_MD_FLEASIZE) ? (offset + 2) :
-                  (offset + 1);
+        /* if anything wrong when unpacking md, we don't check acl
+         * stuff, for simplicity
+         */
+        if (rc)
+                RETURN(rc);
 
         if (md->body->valid & OBD_MD_FLACL_ACCESS) {
-                size = le32_to_cpu(*(__u32 *) lustre_msg_buf(req->rq_repmsg, 
-                                   acl_off, 4));
-                buf = lustre_msg_buf(req->rq_repmsg, acl_off + 1, size);
-
-                acl = posix_acl_from_xattr(buf, size);
-                if (IS_ERR(acl)) {
-                        rc = PTR_ERR(acl);
-                        CERROR("convert xattr to acl failed: %d\n", rc);
-                        RETURN(rc);
-                } else if (acl) {
-                        rc = posix_acl_valid(acl);
-                        if (rc) {
-                                CERROR("acl valid error: %d\n", rc);
-                                posix_acl_release(acl);
-                                RETURN(rc);
+                acl_off = (md->body->valid & OBD_MD_FLEASIZE) ?
+                                (offset + 2) : (offset + 1);
+
+                if (md->body->valid & OBD_MD_RACL) {
+
+                        buf = lustre_swab_repbuf(req, acl_off, sizeof(*perm),
+                                                 lustre_swab_remote_perm);
+                        if (buf == NULL) {
+                                CERROR("Can't unpack remote perm\n");
+                                RETURN(0);
                         }
-                }
 
-                md->acl_access = acl;
+                        OBD_ALLOC(perm, sizeof(*perm));
+                        if (!perm)
+                                RETURN(0);
+                        memcpy(perm, buf, sizeof(*perm));
+
+                        md->remote_perm = perm;
+                } else {
+                        size = le32_to_cpu(*(__u32 *) lustre_msg_buf(
+                                           req->rq_repmsg, acl_off, 4));
+                        buf = lustre_msg_buf(req->rq_repmsg, acl_off + 1, size);
+
+                        acl = posix_acl_from_xattr(buf, size);
+                        if (IS_ERR(acl)) {
+                                rc = PTR_ERR(acl);
+                                CERROR("convert xattr to acl failed: %d\n", rc);
+                                RETURN(0);
+                        } else if (acl) {
+                                rc = posix_acl_valid(acl);
+                                if (rc) {
+                                        CERROR("acl valid error: %d\n", rc);
+                                        posix_acl_release(acl);
+                                        RETURN(0);
+                                }
+                        }
+
+                        md->posix_acl = acl;
+                }
         }
+
         RETURN(rc);
 }
 
@@ -1487,6 +1553,7 @@ struct md_ops mdc_md_ops = {
         .m_get_real_obd  = mdc_get_real_obd,
         .m_change_cbdata_name = mdc_change_cbdata_name,
         .m_change_cbdata = mdc_change_cbdata,
+        .m_access_check  = mdc_access_check,
 };
 
 int __init mdc_init(void)
index c534ab4..16d09e8 100644 (file)
@@ -1022,8 +1022,9 @@ int mds_pack_ealist(struct dentry *dentry, struct ptlrpc_request *req,
         RETURN(rc);
 }
 
-int mds_pack_acl(struct obd_device *obd, struct lustre_msg *repmsg, int offset,
-                 struct mds_body *body, struct inode *inode)
+static
+int mds_pack_posix_acl(struct lustre_msg *repmsg, int offset,
+                       struct mds_body *body, struct inode *inode)
 {
         struct dentry de = { .d_inode = inode };
         __u32 buflen, *sizep;
@@ -1056,45 +1057,77 @@ int mds_pack_acl(struct obd_device *obd, struct lustre_msg *repmsg, int offset,
         RETURN(0);
 }
 
-/* 
- * here we take simple rule: once uid/fsuid is root, we also squash
- * the gid/fsgid, don't care setuid/setgid attributes.
- */
-int mds_squash_root(struct mds_obd *mds, struct mds_req_sec_desc *rsd,
-                    ptl_nid_t *peernid)
+static
+int mds_pack_remote_perm(struct ptlrpc_request *req, int reply_off,
+                         struct mds_body *body, struct inode *inode)
 {
-        if (!mds->mds_squash_uid || *peernid == mds->mds_nosquash_nid)
-                return 0;
+        struct lustre_sec_desc *lsd;
+        struct mds_remote_perm *perm;
+        __u32 lsd_perms;
 
-        if (rsd->rsd_uid && rsd->rsd_fsuid)
-                return 0;
+        LASSERT(inode->i_op);
+        LASSERT(inode->i_op->permission);
+        LASSERT(req->rq_export->exp_mds_data.med_remote);
 
-        CDEBUG(D_SEC, "squash req from "LPX64":"
-               "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", *peernid,
-                rsd->rsd_uid, rsd->rsd_gid,
-                rsd->rsd_fsuid, rsd->rsd_fsgid, rsd->rsd_cap,
-                rsd->rsd_uid ? rsd->rsd_uid : mds->mds_squash_uid,
-                rsd->rsd_uid ? rsd->rsd_gid : mds->mds_squash_gid,
-                rsd->rsd_fsuid ? rsd->rsd_fsuid : mds->mds_squash_uid,
-                rsd->rsd_fsuid ? rsd->rsd_fsgid : mds->mds_squash_gid,
-                rsd->rsd_cap & ~CAP_FS_MASK);
+        perm = (struct mds_remote_perm *)
+                        lustre_msg_buf(req->rq_repmsg, reply_off, sizeof(perm));
+        if (!perm)
+                return -EINVAL;
 
-        if (rsd->rsd_uid == 0) {
-                rsd->rsd_uid = mds->mds_squash_uid;
-                rsd->rsd_gid = mds->mds_squash_gid;
-        }
-        if (rsd->rsd_fsuid == 0) {
-                rsd->rsd_fsuid = mds->mds_squash_uid;
-                rsd->rsd_fsgid = mds->mds_squash_gid;
+        memset(perm, 0, sizeof(*perm));
+
+        /* obtain authenticated uid/gid and LSD permissions, which
+         * might be different from current process context, from LSD
+         */
+        lsd = mds_get_lsd(current->uid);
+        if (!lsd) {
+                CWARN("can't LSD of uid %u\n", current->uid);
+                RETURN(-EPERM);
         }
-        rsd->rsd_cap &= ~CAP_FS_MASK;
 
-        return 1;
+        perm->mrp_auth_uid = lsd->lsd_uid;
+        perm->mrp_auth_gid = lsd->lsd_gid;
+
+        lsd_perms = mds_lsd_get_perms(lsd, 1, 0, req->rq_peer.peer_id.nid);
+        if (lsd_perms & LSD_PERM_SETUID)
+                perm->mrp_allow_setuid = 1;
+        if (lsd_perms & LSD_PERM_SETGID)
+                perm->mrp_allow_setgid = 1;
+
+        mds_put_lsd(lsd);
+
+        /* permission bits of current user
+         * XXX this is low efficient, could we do it in one blow?
+         */
+        if (inode->i_op->permission(inode, MAY_EXEC, NULL) == 0)
+                perm->mrp_perm |= MAY_EXEC;
+        if (inode->i_op->permission(inode, MAY_WRITE, NULL) == 0)
+                perm->mrp_perm |= MAY_WRITE;
+        if (inode->i_op->permission(inode, MAY_READ, NULL) == 0)
+                perm->mrp_perm |= MAY_READ;
+
+        body->valid |= (OBD_MD_FLACL_ACCESS | OBD_MD_RACL);
+
+        RETURN(0);
+}
+
+int mds_pack_acl(struct ptlrpc_request *req, int reply_off,
+                 struct mds_body *body, struct inode *inode)
+{
+        int rc;
+
+        if (!req->rq_export->exp_mds_data.med_remote)
+                rc = mds_pack_posix_acl(req->rq_repmsg, reply_off, body, inode);
+        else
+                rc = mds_pack_remote_perm(req, reply_off, body, inode);
+
+        return rc;
 }
 
 static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
                                 struct ptlrpc_request *req, int req_off,
-                                struct mds_body *reqbody, int reply_off)
+                                struct mds_body *reqbody, int reply_off,
+                                struct mds_req_sec_desc *rsd)
 {
         struct mds_export_data *med = &req->rq_export->u.eu_mds_data;
         struct inode *inode = dentry->d_inode;
@@ -1145,9 +1178,8 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
         
         if (reqbody->valid & OBD_MD_FLACL_ACCESS) {
                 int inc = (reqbody->valid & OBD_MD_FLEASIZE) ? 2 : 1;
-                rc = mds_pack_acl(obd, req->rq_repmsg, reply_off + inc, 
-                                  body, inode);
-        }                
+                rc = mds_pack_acl(req, reply_off + inc, body, inode);
+        }
 
         if (rc == 0)
                 mds_body_do_reverse_map(med, body);
@@ -1255,8 +1287,12 @@ static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct dentry *de,
         
         /* may co-exist with OBD_MD_FLEASIZE */
         if (body->valid & OBD_MD_FLACL_ACCESS) {
-                size[bufcount++] = 4;
-                size[bufcount++] = xattr_acl_size(LL_ACL_MAX_ENTRIES);
+                if (req->rq_export->exp_mds_data.med_remote) {
+                        size[bufcount++] = sizeof(struct mds_remote_perm);
+                } else {
+                        size[bufcount++] = 4;
+                        size[bufcount++] = xattr_acl_size(LL_ACL_MAX_ENTRIES);
+                }
         }
 
         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) {
@@ -1529,7 +1565,8 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset,
                 }
         }
 
-        rc = mds_getattr_internal(obd, dchild, req, offset, body, reply_offset);
+        rc = mds_getattr_internal(obd, dchild, req, offset, body,
+                                  reply_offset, rsd);
         if (rc)
                 GOTO(cleanup, rc); /* returns the lock to the client */
 
@@ -1609,7 +1646,8 @@ static int mds_getattr(struct ptlrpc_request *req, int offset)
                 GOTO(out_pop, rc);
         }
 
-        req->rq_status = mds_getattr_internal(obd, de, req, offset, body, 0);
+        req->rq_status = mds_getattr_internal(obd, de, req, offset, body,
+                                              0, rsd);
         l_dput(de);
 
         EXIT;
@@ -1619,6 +1657,73 @@ out_pop:
         return rc;
 }
 
+static int mds_access_check(struct ptlrpc_request *req, int offset)
+{
+        struct obd_device *obd = req->rq_export->exp_obd;
+        struct lvfs_run_ctxt saved;
+        struct dentry *de;
+        struct mds_req_sec_desc *rsd;
+        struct mds_body *body;
+        struct lvfs_ucred uc;
+        int rep_size[2] = {sizeof(*body),
+                           sizeof(struct mds_remote_perm)};
+        int rc = 0;
+        ENTRY;
+
+        if (!req->rq_export->exp_mds_data.med_remote) {
+                CERROR("from local client "LPU64"\n", req->rq_peer.peer_id.nid);
+                RETURN(-EINVAL);
+        }
+
+        rsd = lustre_swab_mds_secdesc(req, MDS_REQ_SECDESC_OFF);
+        if (!rsd) {
+                CERROR("Can't unpack security desc\n");
+                RETURN(-EFAULT);
+        }
+
+        body = lustre_swab_reqbuf(req, offset, sizeof(*body),
+                                  lustre_swab_mds_body);
+        if (body == NULL) {
+                CERROR ("Can't unpack body\n");
+                RETURN (-EFAULT);
+        }
+
+        MD_COUNTER_INCREMENT(obd, access_check);
+
+        rc = mds_init_ucred(&uc, req, rsd);
+        if (rc) {
+                CERROR("init ucred error: %d\n", rc);
+                RETURN(rc);
+        }
+        push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+
+        de = mds_id2dentry(obd, &body->id1, NULL);
+        if (IS_ERR(de)) {
+                CERROR("grab ino "LPU64": err %ld\n",
+                       body->id1.li_stc.u.e3s.l3s_ino, PTR_ERR(de));
+                GOTO(out_pop, rc = PTR_ERR(de));
+        }
+
+        rc = lustre_pack_reply(req, 2, rep_size, NULL);
+        if (rc) {
+                CERROR("pack reply error: %d\n", rc);
+                GOTO(out_dput, rc = -EINVAL);
+        }
+
+        body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
+        LASSERT(body);
+
+        rc = mds_pack_remote_perm(req, 1, body, de->d_inode);
+        EXIT;
+
+out_dput:
+        l_dput(de);
+out_pop:
+        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
+        mds_exit_ucred(&uc);
+        return rc;
+}
+
 static int mds_obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
                           unsigned long max_age)
 {
@@ -2634,6 +2739,7 @@ static int mds_msg_check_version(struct lustre_msg *msg)
         case MDS_GETSTATUS:
         case MDS_GETATTR:
         case MDS_GETATTR_LOCK:
+        case MDS_ACCESS_CHECK:
         case MDS_READPAGE:
         case MDS_REINT:
         case MDS_CLOSE:
@@ -2812,6 +2918,12 @@ int mds_handle(struct ptlrpc_request *req)
                 rc = mds_getattr(req, MDS_REQ_REC_OFF);
                 break;
 
+        case MDS_ACCESS_CHECK:
+                DEBUG_REQ(D_INODE, req, "access_check");
+                OBD_FAIL_RETURN(OBD_FAIL_MDS_ACCESS_CHECK_NET, 0);
+                rc = mds_access_check(req, MDS_REQ_REC_OFF);
+                break;
+
         case MDS_GETATTR_LOCK: {
                 struct lustre_handle lockh;
                 DEBUG_REQ(D_INODE, req, "getattr_lock");
@@ -3875,9 +3987,14 @@ static int mds_intent_policy(struct ldlm_namespace *ns,
 
         reply_buffers = 3;
         if (it->opc & ( IT_OPEN | IT_GETATTR | IT_LOOKUP | IT_CHDIR )) {
-                reply_buffers = 5;
-                repsize[3] = 4;
-                repsize[4] = xattr_acl_size(LL_ACL_MAX_ENTRIES);
+                if (req->rq_export->exp_mds_data.med_remote) {
+                        reply_buffers = 4;
+                        repsize[3] = sizeof(struct mds_remote_perm);
+                } else {
+                        reply_buffers = 5;
+                        repsize[3] = 4;
+                        repsize[4] = xattr_acl_size(LL_ACL_MAX_ENTRIES);
+                }
         }
 
         rc = lustre_pack_reply(req, reply_buffers, repsize, NULL);
index 167f674..aa0d14e 100644 (file)
@@ -185,8 +185,6 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
 /* mds/handler.c */
 int mds_getattr_size(struct obd_device *obd, struct dentry *dentry,
                      struct ptlrpc_request *req, struct mds_body *body);
-int mds_squash_root(struct mds_obd *mds, struct mds_req_sec_desc *rsd,
-                    ptl_nid_t *peernid);
 int mds_handle(struct ptlrpc_request *req);
 extern struct lvfs_callback_ops mds_lvfs_ops;
 int mds_dt_clean(struct obd_device *obd);
@@ -242,8 +240,8 @@ int mds_pack_ea(struct dentry *dentry, struct ptlrpc_request *req,
                 struct mds_body *repbody, int req_off, int reply_off);
 int mds_pack_ealist(struct dentry *dentry, struct ptlrpc_request *req,
                     struct mds_body *repbody, int reply_off);
-int mds_pack_acl(struct obd_device *, struct lustre_msg *, int offset,
-                 struct mds_body *, struct inode *);
+int mds_pack_acl(struct ptlrpc_request *req, int reply_off,
+                 struct mds_body *body, struct inode *inode);
 int mds_pack_inode2id(struct obd_device *, struct lustre_id *,
                       struct inode *, int);
 
index eebc9b7..eb3231b 100644 (file)
@@ -514,6 +514,43 @@ int mds_update_unpack(struct ptlrpc_request *req, int offset,
         RETURN(rc);
 }
 
+/* 
+ * here we take simple rule: once uid/fsuid is root, we also squash
+ * the gid/fsgid, don't care setuid/setgid attributes.
+ */
+static
+int mds_squash_root(struct mds_obd *mds, struct mds_req_sec_desc *rsd,
+                    ptl_nid_t *peernid)
+{
+        if (!mds->mds_squash_uid || *peernid == mds->mds_nosquash_nid)
+                return 0;
+
+        if (rsd->rsd_uid && rsd->rsd_fsuid)
+                return 0;
+
+        CDEBUG(D_SEC, "squash req from "LPX64":"
+               "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", *peernid,
+                rsd->rsd_uid, rsd->rsd_gid,
+                rsd->rsd_fsuid, rsd->rsd_fsgid, rsd->rsd_cap,
+                rsd->rsd_uid ? rsd->rsd_uid : mds->mds_squash_uid,
+                rsd->rsd_uid ? rsd->rsd_gid : mds->mds_squash_gid,
+                rsd->rsd_fsuid ? rsd->rsd_fsuid : mds->mds_squash_uid,
+                rsd->rsd_fsuid ? rsd->rsd_fsgid : mds->mds_squash_gid,
+                rsd->rsd_cap & ~CAP_FS_MASK);
+
+        if (rsd->rsd_uid == 0) {
+                rsd->rsd_uid = mds->mds_squash_uid;
+                rsd->rsd_gid = mds->mds_squash_gid;
+        }
+        if (rsd->rsd_fsuid == 0) {
+                rsd->rsd_fsuid = mds->mds_squash_uid;
+                rsd->rsd_fsgid = mds->mds_squash_gid;
+        }
+        rsd->rsd_cap &= ~CAP_FS_MASK;
+
+        return 1;
+}
+
 /********************************
  * MDS uid/gid mapping handling *
  ********************************/
index 89f7665..deff801 100644 (file)
@@ -748,10 +748,9 @@ static int mds_finish_open(struct ptlrpc_request *req, struct dentry *dchild,
                         }
                 }
         }
-        
-        rc = mds_pack_acl(obd, req->rq_repmsg, 3, body, dchild->d_inode);
+        rc = mds_pack_acl(req, 3, body, dchild->d_inode);
         if (rc < 0) {
-                CERROR("mds_pack_acl: rc = %d\n", rc);
+                CERROR("pack posix acl: rc = %d\n", rc);
                 up(&dchild->d_inode->i_sem);
                 RETURN(rc);
         }
index 4ae4bf5..a597cd4 100644 (file)
@@ -729,6 +729,7 @@ int lprocfs_alloc_md_stats(struct obd_device *obd,
         LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
+        LPROCFS_MD_OP_INIT(num_private_stats, stats, access_check);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_lock);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
index 370fe17..0bfcda2 100644 (file)
@@ -64,6 +64,7 @@ struct ll_rpc_opcode {
         { MDS_UNPIN,        "mds_unpin" },
         { MDS_SYNC,         "mds_sync" },
         { MDS_DONE_WRITING, "mds_done_writing" },
+        { MDS_ACCESS_CHECK, "mds_access_check"},
         { LDLM_ENQUEUE,     "ldlm_enqueue" },
         { LDLM_CONVERT,     "ldlm_convert" },
         { LDLM_CANCEL,      "ldlm_cancel" },
index 1074465..99b667b 100644 (file)
@@ -863,6 +863,13 @@ void lustre_swab_ptlbd_rsp(struct ptlbd_rsp *r)
         __swab16s(&r->r_error_cnt);
 }
 
+void lustre_swab_remote_perm(struct mds_remote_perm *p)
+{
+        __swab32s(&p->mrp_auth_uid);
+        __swab32s(&p->mrp_auth_gid);
+        __swab16s(&p->mrp_perm);
+}
+
 /* no one calls this */
 int llog_log_swabbed(struct llog_log_hdr *hdr)
 {
index c92f34e..dac116b 100644 (file)
@@ -178,6 +178,7 @@ EXPORT_SYMBOL(lustre_swab_lustre_stc);
 EXPORT_SYMBOL(lustre_swab_lustre_fid);
 EXPORT_SYMBOL(lustre_swab_mds_status_req);
 EXPORT_SYMBOL(lustre_swab_mds_secdesc);
+EXPORT_SYMBOL(lustre_swab_remote_perm);
 EXPORT_SYMBOL(lustre_swab_mds_body);
 EXPORT_SYMBOL(lustre_swab_mds_rec_setattr);
 EXPORT_SYMBOL(lustre_swab_mds_rec_create);
index 6244909..927293c 100644 (file)
@@ -430,7 +430,19 @@ void gss_release_msg(struct gss_upcall_msg *gmsg)
                 return;
         }
         LASSERT(list_empty(&gmsg->gum_list));
+#if 0
         LASSERT(list_empty(&gmsg->gum_base.list));
+#else
+        /* XXX */
+        if (!list_empty(&gmsg->gum_base.list)) {
+                CWARN("msg %p: list: %p/%p/%p, copied %d, err %d, wq %d\n",
+                      gmsg, &gmsg->gum_base.list,
+                      gmsg->gum_base.list.prev, gmsg->gum_base.list.next,
+                      gmsg->gum_base.copied, gmsg->gum_base.errno,
+                      list_empty(&gmsg->gum_waitq.task_list));
+                LBUG();
+        }
+#endif
         OBD_FREE(gmsg, sizeof(*gmsg));
         EXIT;
 }
@@ -438,19 +450,15 @@ void gss_release_msg(struct gss_upcall_msg *gmsg)
 static void
 gss_unhash_msg_nolock(struct gss_upcall_msg *gmsg)
 {
-        ENTRY;
-        if (list_empty(&gmsg->gum_list)) {
-                EXIT;
+        LASSERT(spin_is_locked(&gmsg->gum_gsec->gs_lock));
+
+        if (list_empty(&gmsg->gum_list))
                 return;
-        }
 
         list_del_init(&gmsg->gum_list);
         wake_up(&gmsg->gum_waitq);
+        LASSERT(atomic_read(&gmsg->gum_refcount) > 1);
         atomic_dec(&gmsg->gum_refcount);
-        CDEBUG(D_SEC, "gmsg %p refcount now %d\n",
-               gmsg, atomic_read(&gmsg->gum_refcount));
-        LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
-        EXIT;
 }
 
 static void
@@ -471,11 +479,14 @@ struct gss_upcall_msg * gss_find_upcall(struct gss_sec *gsec,
         struct gss_upcall_msg *gmsg;
         ENTRY;
 
+        LASSERT(spin_is_locked(&gsec->gs_lock));
+
         list_for_each_entry(gmsg, &gsec->gs_upcalls, gum_list) {
                 if (memcmp(&gmsg->gum_data, gmd, sizeof(*gmd)))
                         continue;
                 if (strcmp(gmsg->gum_obdname, obdname))
                         continue;
+                LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
                 atomic_inc(&gmsg->gum_refcount);
                 CDEBUG(D_SEC, "found gmsg at %p: obdname %s, uid %d, ref %d\n",
                        gmsg, obdname, gmd->gum_uid,
@@ -501,8 +512,11 @@ static void gss_init_upcall_msg(struct gss_upcall_msg *gmsg,
         memcpy(&gmsg->gum_data, gmd, sizeof(*gmd));
 
         rpcmsg = &gmsg->gum_base;
+        INIT_LIST_HEAD(&rpcmsg->list);
         rpcmsg->data = &gmsg->gum_data;
         rpcmsg->len = sizeof(gmsg->gum_data);
+        rpcmsg->copied = 0;
+        rpcmsg->errno = 0;
         EXIT;
 }
 #endif /* __KERNEL__ */
@@ -1439,7 +1453,7 @@ static void gss_cred_destroy(struct ptlrpc_cred *cred)
                 gss_put_ctx(gcred->gc_ctx);
         }
 
-        CDEBUG(D_SEC, "GSS_SEC: destroy cred %p\n", gcred);
+        CDEBUG(D_SEC, "sec.gss %p: destroy cred %p\n", cred->pc_sec, gcred);
 
         OBD_FREE(gcred, sizeof(*gcred));
         EXIT;
@@ -1585,6 +1599,8 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
         static unsigned long ratelimit;
         ENTRY;
 
+        LASSERT(list_empty(&msg->list));
+
         if (msg->errno >= 0) {
                 EXIT;
                 return;
@@ -1592,12 +1608,13 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 
         gmsg = container_of(msg, struct gss_upcall_msg, gum_base);
         CDEBUG(D_SEC, "destroy gmsg %p\n", gmsg);
+        LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
         atomic_inc(&gmsg->gum_refcount);
         gss_unhash_msg(gmsg);
         if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) {
                 unsigned long now = get_seconds();
                 if (time_after(now, ratelimit)) {
-                        CWARN("GSS_SEC upcall timed out.\n"
+                        CWARN("sec.gss upcall timed out.\n"
                               "Please check user daemon is running!\n");
                         ratelimit = now + 15;
                 }
@@ -1622,6 +1639,7 @@ void gss_pipe_release(struct inode *inode)
 
                 gmsg = list_entry(gsec->gs_upcalls.next,
                                   struct gss_upcall_msg, gum_list);
+                LASSERT(list_empty(&gmsg->gum_base.list));
                 gmsg->gum_base.errno = -EPIPE;
                 atomic_inc(&gmsg->gum_refcount);
                 gss_unhash_msg_nolock(gmsg);
@@ -1711,8 +1729,7 @@ struct ptlrpc_sec* gss_create_sec(__u32 flavor,
 
         current->fsuid = save_uid;
 
-        CDEBUG(D_SEC, "Create GSS security instance at %p(external %p)\n",
-               gsec, sec);
+        CDEBUG(D_SEC, "Create sec.gss %p\n", gsec);
         RETURN(sec);
 
 #ifdef __KERNEL__
@@ -1743,7 +1760,7 @@ void gss_destroy_sec(struct ptlrpc_sec *sec)
         ENTRY;
 
         gsec = container_of(sec, struct gss_sec, gs_base);
-        CDEBUG(D_SEC, "Destroy GSS security instance at %p\n", gsec);
+        CDEBUG(D_SEC, "Destroy sec.gss %p\n", gsec);
 
         LASSERT(gsec->gs_mech);
         LASSERT(!atomic_read(&sec->ps_refcount));
index 5958518..3ae8467 100644 (file)
@@ -236,7 +236,7 @@ gssd_upcall(struct rsi *item, struct cache_req *chandle)
                 }
         }
         cache_get(&item->h);
-        //set_bit(CACHE_HASHED, &item->h.flags);
+        set_bit(CACHE_HASHED, &item->h.flags);
         item->h.next = *head;
         *head = &item->h;
         rsi_cache.entries++;
index ce8d203..23ed9f9 100644 (file)
@@ -84,7 +84,7 @@ int ptlrpcs_unregister(struct ptlrpc_sec_type *type)
         LASSERT(sectypes[major] == type);
 
         if (atomic_read(&type->pst_inst)) {
-                CERROR("%s: still have %d, instances\n",
+                CERROR("%s: still have %d instances\n",
                        type->pst_name, atomic_read(&type->pst_inst));
                 spin_unlock(&sectypes_lock);
                 return -EINVAL;
@@ -303,6 +303,9 @@ int flush_credcache(struct ptlrpc_sec *sec, uid_t uid,
                                 if (!force)
                                         continue;
                                 list_del_init(&cred->pc_hash);
+                                CDEBUG(D_SEC, "sec %p: flush busy(%d) cred %p "
+                                       "by force\n", sec,
+                                       atomic_read(&cred->pc_refcount), cred);
                         } else
                                 list_move(&cred->pc_hash, &freelist);
 
index bda2d1b..4eec3ac 100644 (file)
@@ -79,7 +79,7 @@ static void null_cred_destroy(struct ptlrpc_cred *cred)
 {
         LASSERT(!atomic_read(&cred->pc_refcount));
 
-        CDEBUG(D_SEC, "NULL_SEC: destroy cred %p\n", cred);
+        CDEBUG(D_SEC, "sec.null %p: destroy cred %p\n", cred->pc_sec, cred);
         OBD_FREE(cred, sizeof(*cred));
 }
 
@@ -109,7 +109,7 @@ struct ptlrpc_sec* null_create_sec(__u32 flavor,
         sec->ps_nextgc = 0; /* never do gc */
         sec->ps_flags = 0;
 
-        CDEBUG(D_SEC, "Create NULL security module at %p\n", sec);
+        CDEBUG(D_SEC, "Create sec.null module at %p\n", sec);
         RETURN(sec);
 }
 
@@ -118,7 +118,7 @@ void null_destroy_sec(struct ptlrpc_sec *sec)
 {
         ENTRY;
 
-        CDEBUG(D_SEC, "Destroy NULL security module at %p\n", sec);
+        CDEBUG(D_SEC, "Destroy sec.null %p\n", sec);
 
         LASSERT(!atomic_read(&sec->ps_refcount));
         OBD_FREE(sec, sizeof(*sec));
@@ -170,7 +170,7 @@ int ptlrpcs_null_init(void)
 
         rc = ptlrpcs_register(&null_type);
         if (rc)
-                CERROR("failed to register NULL security: %d\n", rc);
+                CERROR("failed to register sec.null: %d\n", rc);
 
         return rc;
 }
@@ -181,7 +181,7 @@ int ptlrpcs_null_exit(void)
 
         rc = ptlrpcs_unregister(&null_type);
         if (rc)
-                CERROR("cannot unregister NULL security: %d\n", rc);
+                CERROR("cannot unregister sec.null: %d\n", rc);
 
         return rc;
 }
index 3682f8d..db867b6 100644 (file)
@@ -793,6 +793,7 @@ main(int argc, char **argv)
         CHECK_VALUE(MDS_UNPIN);
         CHECK_VALUE(MDS_SYNC);
         CHECK_VALUE(MDS_DONE_WRITING);
+        CHECK_VALUE(MDS_ACCESS_CHECK);
         CHECK_VALUE(MDS_LAST_OPC);
 
         CHECK_VALUE(REINT_SETATTR);