From 39e41752293f4e34a32626b93a87455c61a42faa Mon Sep 17 00:00:00 2001 From: ericm Date: Wed, 13 Jul 2005 00:59:04 +0000 Subject: [PATCH] land b_hd_sec: perm/acl authorization for remote users. --- lustre/include/linux/lustre_idl.h | 23 +- lustre/include/linux/lustre_lite.h | 7 +- lustre/include/linux/obd.h | 2 + lustre/include/linux/obd_class.h | 11 + lustre/include/linux/obd_support.h | 2 + lustre/llite/file.c | 33 +-- lustre/llite/llite_internal.h | 39 ++++ lustre/llite/llite_lib.c | 453 ++++++++++++++++++++++++++++++++++++- lustre/llite/namei.c | 9 + lustre/lmv/lmv_obd.c | 19 ++ lustre/lov/lov_obd.c | 1 - lustre/mdc/mdc_request.c | 113 +++++++-- lustre/mds/handler.c | 199 ++++++++++++---- lustre/mds/mds_internal.h | 6 +- lustre/mds/mds_lib.c | 37 +++ lustre/mds/mds_open.c | 5 +- lustre/obdclass/lprocfs_status.c | 1 + lustre/ptlrpc/lproc_ptlrpc.c | 1 + lustre/ptlrpc/pack_generic.c | 7 + lustre/ptlrpc/ptlrpc_module.c | 1 + lustre/sec/gss/sec_gss.c | 43 ++-- lustre/sec/gss/svcsec_gss.c | 2 +- lustre/sec/sec.c | 5 +- lustre/sec/sec_null.c | 10 +- lustre/utils/wirecheck.c | 1 + 25 files changed, 910 insertions(+), 120 deletions(-) diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 5441eb7..a20a8a0 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -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; diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index afa7475..2276cec 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -39,6 +39,9 @@ #include +/* 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 diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index deca7ec..ff20fe3 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -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 **); diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 6554d4f..03c9567 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -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) { diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index f6508c0..a7ec412 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -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 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 6fc869f..54233fc 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index eaef944..363df56 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 84f3263..97cf2e8 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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 diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index a0c8916..9cad4e7 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -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)) diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 86f3035..e21076e 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -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) diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 891c132..f429eba 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -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) { diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index fc4dc6d..666782e 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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) diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index c534ab4..16d09e8 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -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); diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 167f674..aa0d14e 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -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); diff --git a/lustre/mds/mds_lib.c b/lustre/mds/mds_lib.c index eebc9b7..eb3231b 100644 --- a/lustre/mds/mds_lib.c +++ b/lustre/mds/mds_lib.c @@ -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 * ********************************/ diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index 89f7665..deff801 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -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); } diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 4ae4bf5..a597cd4 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -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); diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index 370fe17..0bfcda2 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -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" }, diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index 1074465..99b667b 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -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) { diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c index c92f34e..dac116b 100644 --- a/lustre/ptlrpc/ptlrpc_module.c +++ b/lustre/ptlrpc/ptlrpc_module.c @@ -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); diff --git a/lustre/sec/gss/sec_gss.c b/lustre/sec/gss/sec_gss.c index 6244909..927293c 100644 --- a/lustre/sec/gss/sec_gss.c +++ b/lustre/sec/gss/sec_gss.c @@ -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)); diff --git a/lustre/sec/gss/svcsec_gss.c b/lustre/sec/gss/svcsec_gss.c index 5958518..3ae8467 100644 --- a/lustre/sec/gss/svcsec_gss.c +++ b/lustre/sec/gss/svcsec_gss.c @@ -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++; diff --git a/lustre/sec/sec.c b/lustre/sec/sec.c index ce8d203..23ed9f9 100644 --- a/lustre/sec/sec.c +++ b/lustre/sec/sec.c @@ -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(§ypes_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); diff --git a/lustre/sec/sec_null.c b/lustre/sec/sec_null.c index bda2d1b..4eec3ac 100644 --- a/lustre/sec/sec_null.c +++ b/lustre/sec/sec_null.c @@ -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; } diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index 3682f8d..db867b6 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -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); -- 1.8.3.1