MDS QOS usage of statfs, it should not stuck in waiting.
Severity : enhancement
+Bugzilla : 11842
+Description: remote_acl support
+Details : Support ACL-based permission check for remote user.
+ Support setfacl/getfacl for remote user with the utils
+ "lfs {l,r}{s,g}etfacl" which follow the same parameter format as
+ the system "{s,g}etfacl" utils.
+
+Severity : enhancement
Bugzilla : 14288
Description: Update to RHEL4 U6 kernel-2.6.9-67.EL.
AC_DEFINE_UNQUOTED(KRB5_VERSION, $K5VERS, [Define this as the Kerberos version number])
if test -f $dir/include/gssapi/gssapi_krb5.h -a \
\( -f $dir/lib/libgssapi_krb5.a -o \
+ -f $dir/lib64/libgssapi_krb5.a -o \
+ -f $dir/lib64/libgssapi_krb5.so -o \
-f $dir/lib/libgssapi_krb5.so \) ; then
AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
KRBDIR="$dir"
AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
+ dnl Check for newer error message facility
+ AC_CHECK_LIB($gssapi_lib, krb5_get_error_message,
+ AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE, 1, [Define this if the function krb5_get_error_message is available]), ,$KRBLIBS)
+
+ dnl Check for function to specify addressless tickets
+ AC_CHECK_LIB($gssapi_lib, krb5_get_init_creds_opt_set_addressless,
+ AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS, 1, [Define this if the function krb5_get_init_creds_opt_set_addressless is available]), ,$KRBLIBS)
+
dnl If they specified a directory and it didn't work, give them a warning
if test "x$krb5_with" != "x" -a "$krb5_with" != "$KRBDIR"; then
AC_MSG_WARN(Using $KRBDIR instead of requested value of $krb5_with for Kerberos!)
obd_cache.h obd_class.h obd_echo.h obd.h obd_lov.h \
obd_ost.h obd_support.h lustre_ver.h lu_object.h lu_time.h \
md_object.h dt_object.h lustre_param.h lustre_mdt.h \
- lustre_fid.h lustre_fld.h lustre_req_layout.h lustre_capa.h
-
+ lustre_fid.h lustre_fld.h lustre_req_layout.h lustre_capa.h \
+ lustre_idmap.h lustre_eacl.h
# ifdef CONFIG_FS_POSIX_ACL
# ifdef HAVE_XATTR_ACL
# include <linux/xattr_acl.h>
-# endif
+# endif /* HAVE_XATTR_ACL */
# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
# include <linux/posix_acl_xattr.h>
-# endif
-# endif
+# endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
# ifndef HAVE_VFS_INTENT_PATCHES
# include <linux/lustre_intent.h>
# endif
-#endif
+#endif /* __KERNEL__ */
/* ACL */
#ifdef CONFIG_FS_POSIX_ACL
# define LUSTRE_POSIX_ACL_MAX_SIZE XATTR_ACL_SIZE
-#else /* CONFIG_FS_POSIX_ACL */
+# else /* CONFIG_FS_POSIX_ACL */
# define LUSTRE_POSIX_ACL_MAX_SIZE 0
-#endif /* CONFIG_FS_POSIX_ACL */
+# endif /* CONFIG_FS_POSIX_ACL */
#endif /* _LUSTRE_ACL_H */
# ifdef CONFIG_FS_POSIX_ACL
# ifdef HAVE_XATTR_ACL
# include <linux/xattr_acl.h>
-# endif
+# endif /* HAVE_XATTR_ACL */
# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
# include <linux/posix_acl_xattr.h>
-# endif
-# endif
+# endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
# ifndef HAVE_VFS_INTENT_PATCHES
# include <linux/lustre_intent.h>
# endif
-#endif
+#endif /* __KERNEL__ */
struct mds_obd;
struct ptlrpc_request;
__u32 luc_cap;
__u32 luc_umask;
struct group_info *luc_ginfo;
- struct mdt_identity *luc_identity;
+ struct md_identity *luc_identity;
};
struct lvfs_callback_ops {
extern int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk);
extern int llapi_quotactl(char *mnt, struct if_quotactl *qctl);
extern int llapi_target_iterate(int type_num, char **obd_type, void *args, llapi_cb_t cb);
-extern int llapi_getfacl(char *fname, char *cmd);
-extern int llapi_setfacl(char *fname, char *cmd);
+extern int llapi_lsetfacl(int argc, char *argv[]);
+extern int llapi_lgetfacl(int argc, char *argv[]);
+extern int llapi_rsetfacl(int argc, char *argv[]);
+extern int llapi_rgetfacl(int argc, char *argv[]);
+extern int llapi_cp(int argc, char *argv[]);
+extern int llapi_ls(int argc, char *argv[]);
#endif
#define XATTR_NAME_ACL_DEFAULT "system.posix_acl_default"
#define XATTR_NAME_LOV "trusted.lov"
-/* remote ACL */
-#define XATTR_NAME_LUSTRE_ACL "system.lustre_acl"
-
#define OBD_MD_FLID (0x00000001ULL) /* object ID */
#define OBD_MD_FLATIME (0x00000002ULL) /* access time */
#define OBD_MD_FLMTIME (0x00000004ULL) /* data modification time */
#define OBD_MD_FLCKSPLIT (0x0000080000000000ULL) /* Check split on server */
#define OBD_MD_FLCROSSREF (0x0000100000000000ULL) /* Cross-ref case */
+#define OBD_MD_FLRMTLSETFACL (0x0001000000000000ULL) /* lfs lsetfacl case */
+#define OBD_MD_FLRMTLGETFACL (0x0002000000000000ULL) /* lfs lgetfacl case */
+#define OBD_MD_FLRMTRSETFACL (0x0004000000000000ULL) /* lfs rsetfacl case */
+#define OBD_MD_FLRMTRGETFACL (0x0008000000000000ULL) /* lfs rgetfacl case */
+
#define OBD_MD_FLGETATTR (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME | \
OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLBLKSZ | \
OBD_MD_FLMODE | OBD_MD_FLTYPE | OBD_MD_FLUID | \
__u32 rp_access_perm; /* MAY_READ/WRITE/EXEC */
};
-/* setxid permissions for mds_setxid_perm.mp_perm */
-#define LUSTRE_SETUID_PERM 0x01
-#define LUSTRE_SETGID_PERM 0x02
-#define LUSTRE_SETGRP_PERM 0x04
+/* permissions for md_perm.mp_perm */
+enum {
+ CFS_SETUID_PERM = 0x01,
+ CFS_SETGID_PERM = 0x02,
+ CFS_SETGRP_PERM = 0x04,
+ CFS_RMTACL_PERM = 0x08
+};
extern void lustre_swab_mds_remote_perm(struct mds_remote_perm *p);
#define MAY_VTX_PART (1 << 12)
/* full VTX permission check */
#define MAY_VTX_FULL (1 << 13)
+/* lfs rgetfacl permission check */
+#define MAY_RGETFACL (1 << 14)
enum {
MDS_CHECK_SPLIT = 1 << 0,
#define IOC_OBD_STATFS _IOWR('f', 164, struct obd_statfs *)
#define IOC_LOV_GETINFO _IOWR('f', 165, struct lov_user_mds_data *)
#define LL_IOC_FLUSHCTX _IOW ('f', 166, long)
-#define LL_IOC_GETFACL _IOWR('f', 167, struct rmtacl_ioctl_data *)
-#define LL_IOC_SETFACL _IOWR('f', 168, struct rmtacl_ioctl_data *)
+#define LL_IOC_RMTACL _IOW ('f', 167, long)
#define LL_IOC_LLOOP_ATTACH _IOWR('f', 169, long)
#define LL_IOC_LLOOP_DETACH _IOWR('f', 170, long)
#define LL_FILE_IGNORE_LOCK 0x00000001
#define LL_FILE_GROUP_LOCKED 0x00000002
#define LL_FILE_READAHEAD 0x00000004
+#define LL_FILE_RMTACL 0x00000008
#define LOV_USER_MAGIC_V1 0x0BD10BD0
#define LOV_USER_MAGIC LOV_USER_MAGIC_V1
#define IDENTITY_DOWNCALL_MAGIC 0x6d6dd620
-/* setxid permission */
-#define N_SETXID_PERMS_MAX 64
+/* permission */
+#define N_PERMS_MAX 64
-struct setxid_perm_downcall_data {
+struct perm_downcall_data {
__u64 pdd_nid;
__u32 pdd_perm;
};
__u32 idd_uid;
__u32 idd_gid;
__u32 idd_nperms;
- struct setxid_perm_downcall_data idd_perms[N_SETXID_PERMS_MAX];
+ struct perm_downcall_data idd_perms[N_PERMS_MAX];
__u32 idd_ngroups;
__u32 idd_groups[0];
};
-#define RMTACL_DOWNCALL_MAGIC 0x6d6dd620
-#define RMTACL_SIZE_MAX (4096)
+/* for non-mapped uid/gid */
+#define NOBODY_UID 99
+#define NOBODY_GID 99
-struct rmtacl_downcall_data {
- __u32 add_magic;
- __u32 add_handle;
- __u64 add_key;
- __u32 add_buflen;
- __u32 add_padding;
- __u8 add_buf[0];
+#define INVALID_ID (-1)
+
+enum {
+ RMT_LSETFACL = 1,
+ RMT_LGETFACL = 2,
+ RMT_RSETFACL = 3,
+ RMT_RGETFACL = 4
};
#ifdef NEED_QUOTA_DEFS
# define offsetof(typ,memb) ((unsigned long)((char *)&(((typ *)0)->memb)))
#endif
-/* remote acl ioctl */
-struct rmtacl_ioctl_data {
- char *cmd; /* IN */
- unsigned long cmd_len;
- char *res; /* OUT */
- unsigned long res_len;
-};
-
#endif /* _LUSTRE_USER_H */
LCFG_LOV_ADD_INA = 0x00ce013,
LCFG_ADD_MDC = 0x00cf014,
LCFG_DEL_MDC = 0x00cf015,
- LCFG_SEC_FLAVOR = 0x00ce016,
+ LCFG_SPTLRPC_CONF = 0x00cf016,
};
struct lustre_cfg_bufs {
RETURN(0);
}
-/* default value for nllu/nllg for llite */
-#define NOBODY_UID 99
-#define NOBODY_GID 99
+#include <lustre/lustre_user.h>
+
#define INVALID_UID (-1)
#endif // _LUSTRE_CFG_H
int lmd_exclude_count;
char *lmd_dev; /* device name */
char *lmd_profile; /* client only */
- char *lmd_sec_mdt; /* sec from mdt (to ost/mdt) */
- char *lmd_sec_cli; /* sec from client (to ost/mdt) */
- uid_t lmd_nllu; /* non-lustre-local-user id */
- gid_t lmd_nllg; /* non-lustre-local-group id */
char *lmd_opts; /* lustre mount options (as opposed to
_device_ mount options) */
__u32 *lmd_exclude; /* array of OSTs to ignore */
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * This file is part of Lustre, http://www.lustre.org
+ *
+ * MDS data structures.
+ * See also lustre_idl.h for wire formats of requests.
+ */
+
+#ifndef _LUSTRE_EACL_H
+#define _LUSTRE_EACL_H
+
+#ifdef CONFIG_FS_POSIX_ACL
+
+# ifdef HAVE_XATTR_ACL
+# include <linux/xattr_acl.h>
+# endif /* HAVE_XATTR_ACL */
+# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+# include <linux/posix_acl_xattr.h>
+# endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+
+#include <lustre_idmap.h>
+#include <md_object.h>
+#include <lu_object.h>
+
+typedef struct {
+ __u16 e_tag;
+ __u16 e_perm;
+ __u32 e_id;
+ __u32 e_stat;
+} ext_acl_xattr_entry;
+
+typedef struct {
+ __u32 a_count;
+ ext_acl_xattr_entry a_entries[0];
+} ext_acl_xattr_header;
+
+#define CFS_ACL_XATTR_SIZE(count, prefix) \
+ (sizeof(prefix ## _header) + (count) * sizeof(prefix ## _entry))
+
+#define CFS_ACL_XATTR_COUNT(size, prefix) \
+ (((size) - sizeof(prefix ## _header)) / sizeof(prefix ## _entry))
+
+extern int lustre_posix_acl_permission(struct md_ucred *mu, struct lu_attr *la,
+ int want, posix_acl_xattr_entry *entry,
+ int count);
+extern int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
+ __u32 mode, int count);
+extern int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry,
+ __u32 *pmode, int count);
+
+extern ext_acl_xattr_header *
+lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size);
+extern int
+lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
+ posix_acl_xattr_header **out);
+extern int
+lustre_posix_acl_xattr_id2client(struct md_ucred *mu,
+ struct lustre_idmap_table *t,
+ posix_acl_xattr_header *header,
+ int size, int flags);
+extern void
+lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size);
+extern int
+lustre_ext_acl_xattr_id2server(struct md_ucred *mu,
+ struct lustre_idmap_table *t,
+ ext_acl_xattr_header *header);
+extern void
+lustre_ext_acl_xattr_free(ext_acl_xattr_header *header);
+extern int
+lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
+ ext_acl_xattr_header *ext_header,
+ posix_acl_xattr_header **out);
+extern ext_acl_xattr_header *
+lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
+ ext_acl_xattr_header *ext_header);
+
+#endif /* CONFIG_FS_POSIX_ACL */
+
+#endif
loff_t med_lr_off;
int med_lr_idx;
unsigned int med_rmtclient:1; /* remote client? */
- __u32 med_nllu;
- __u32 med_nllg;
- struct mds_idmap_table *med_idmap;
+ struct semaphore med_idmap_sem;
+ struct lustre_idmap_table *med_idmap;
};
struct mdt_export_data {
loff_t med_lr_off;
int med_lr_idx;
unsigned int med_rmtclient:1; /* remote client? */
- __u32 med_nllu;
- __u32 med_nllg;
- struct mdt_idmap_table *med_idmap;
+ struct semaphore med_idmap_sem;
+ struct lustre_idmap_table *med_idmap;
};
struct osc_creator {
exp_req_replay_needed:1,
exp_lock_replay_needed:1,
exp_need_sync:1,
+ exp_flvr_changed:1,
+ exp_flvr_adapt:1,
exp_libclient:1; /* liblustre client? */
+ /* also protected by exp_lock */
+ enum lustre_sec_part exp_sp_peer;
+ struct sptlrpc_flavor exp_flvr; /* current */
+ struct sptlrpc_flavor exp_flvr_old[2]; /* about-to-expire */
+ cfs_time_t exp_flvr_expire[2]; /* seconds */
+
union {
struct mds_export_data eu_mds_data;
struct mdt_export_data eu_mdt_data;
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * This file is part of Lustre, http://www.lustre.org
+ *
+ * MDS data structures.
+ * See also lustre_idl.h for wire formats of requests.
+ */
+
+#ifndef _LUSTRE_IDMAP_H
+#define _LUSTRE_IDMAP_H
+
+#include <md_object.h>
+
+#define CFS_NGROUPS_PER_BLOCK ((int)(CFS_PAGE_SIZE / sizeof(gid_t)))
+
+#define CFS_GROUP_AT(gi, i) \
+ ((gi)->blocks[(i) / CFS_NGROUPS_PER_BLOCK][(i) % CFS_NGROUPS_PER_BLOCK])
+
+enum {
+ CFS_IC_NOTHING = 0, /* convert nothing */
+ CFS_IC_ALL = 1, /* convert all items */
+ CFS_IC_MAPPED = 2, /* convert mapped uid/gid */
+ CFS_IC_UNMAPPED = 3 /* convert unmapped uid/gid */
+};
+
+#define CFS_IDMAP_NOTFOUND (-1)
+
+#define CFS_IDMAP_HASHSIZE 32
+
+enum lustre_idmap_idx {
+ RMT_UIDMAP_IDX,
+ LCL_UIDMAP_IDX,
+ RMT_GIDMAP_IDX,
+ LCL_GIDMAP_IDX,
+ CFS_IDMAP_N_HASHES
+};
+
+struct lustre_idmap_table {
+ spinlock_t lit_lock;
+ struct list_head lit_idmaps[CFS_IDMAP_N_HASHES][CFS_IDMAP_HASHSIZE];
+};
+
+extern void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist);
+extern void lustre_groups_sort(struct group_info *group_info);
+extern int lustre_in_group_p(struct md_ucred *mu, gid_t grp);
+
+extern int lustre_idmap_add(struct lustre_idmap_table *t,
+ uid_t ruid, uid_t luid,
+ gid_t rgid, gid_t lgid);
+extern int lustre_idmap_del(struct lustre_idmap_table *t,
+ uid_t ruid, uid_t luid,
+ gid_t rgid, gid_t lgid);
+extern int lustre_idmap_lookup_uid(struct md_ucred *mu,
+ struct lustre_idmap_table *t,
+ int reverse, uid_t uid);
+extern int lustre_idmap_lookup_gid(struct md_ucred *mu,
+ struct lustre_idmap_table *t,
+ int reverse, gid_t gid);
+extern struct lustre_idmap_table *lustre_idmap_init(void);
+extern void lustre_idmap_fini(struct lustre_idmap_table *t);
+
+#endif
struct obd_device *imp_obd;
struct ptlrpc_sec *imp_sec;
+ struct semaphore imp_sec_mutex;
+ cfs_time_t imp_sec_expire;
cfs_waitq_t imp_recovery_waitq;
atomic_t imp_inflight;
# ifdef CONFIG_FS_POSIX_ACL
# ifdef HAVE_XATTR_ACL
# include <linux/xattr_acl.h>
-# endif
+# endif /*HAVE_XATTR_ACL */
# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
# include <linux/posix_acl_xattr.h>
-# endif
-# endif
+# endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
# ifndef HAVE_VFS_INTENT_PATCHES
# include <linux/lustre_intent.h>
-# endif
-#endif
+# endif /* HAVE_VFS_INTENT_PATCHES */
+#endif /* __KERNEL__ */
#include <lustre_handles.h>
#include <libcfs/kp30.h>
#include <lustre/lustre_idl.h>
struct req_capsule cti_pill;
};
-/* id map */
-#define MDT_IDMAP_HASHSIZE (32)
-#define MDT_IDMAP_HASHFUNC(id) ((id) & (MDT_IDMAP_HASHSIZE - 1))
-
-enum mdt_idmap_idx {
- RMT_UIDMAP_IDX,
- LCL_UIDMAP_IDX,
- RMT_GIDMAP_IDX,
- LCL_GIDMAP_IDX,
- MDT_IDMAP_N_HASHES
-};
-
-struct mdt_idmap_table {
- spinlock_t mit_lock;
- struct list_head mit_idmaps[MDT_IDMAP_N_HASHES]
- [MDT_IDMAP_HASHSIZE];
-};
-
enum {
ESERIOUS = 0x0001000
};
struct ptlrpc_cli_ctx *rq_cli_ctx; /* client's half ctx */
struct ptlrpc_svc_ctx *rq_svc_ctx; /* server's half ctx */
struct list_head rq_ctx_chain; /* link to waited ctx */
- ptlrpc_sec_flavor_t rq_sec_flavor; /* client & server */
- /* client security flags */
- unsigned long rq_ctx_init:1, /* context initiation */
+
+ struct sptlrpc_flavor rq_flvr; /* client & server */
+ enum lustre_sec_part rq_sp_from;
+
+ unsigned long /* client/server security flags */
+ rq_ctx_init:1, /* context initiation */
rq_ctx_fini:1, /* context destroy */
rq_bulk_read:1, /* request bulk read */
rq_bulk_write:1, /* request bulk write */
rq_auth_remote:1, /* authed as remote user */
rq_auth_usr_root:1, /* authed as root */
rq_auth_usr_mdt:1, /* authed as mdt */
+ /* security tfm flags */
+ rq_pack_udesc:1,
+ rq_pack_bulk:1,
/* doesn't expect reply FIXME */
rq_no_reply:1;
#define PARAM_MDC "mdc."
#define PARAM_LLITE "llite."
#define PARAM_LOV "lov."
+#define PARAM_SRPC "srpc."
+#define PARAM_SRPC_FLVR "srpc.flavor."
+#define PARAM_SRPC_UDESC "srpc.udesc.cli2mdt"
#define PARAM_SEC "security."
-#define PARAM_SEC_RPC PARAM_SEC"rpc."
-#define PARAM_SEC_RPC_MDT PARAM_SEC_RPC"mdt="
-#define PARAM_SEC_RPC_CLI PARAM_SEC_RPC"cli="
#endif /* _LUSTRE_PARAM_H */
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
+ * Copyright (C) 2004-2007 Cluster File Systems, Inc.
*
* This file is part of Lustre, http://www.lustre.org.
*
struct ptlrpc_reply_state;
struct ptlrpc_bulk_desc;
struct brw_page;
+struct seq_file;
/*
* forward declaration
SPTLRPC_POLICY_NULL = 0,
SPTLRPC_POLICY_PLAIN = 1,
SPTLRPC_POLICY_GSS = 2,
- SPTLRPC_POLICY_GSS_PIPEFS = 3,
SPTLRPC_POLICY_MAX,
};
};
/*
- * flavor compose/extract
+ * rpc flavor compose/extract, represented as 16 bits
+ *
+ * 4b (reserved) | 4b (svc) | 4b (mech) | 4b (policy)
*/
+#define RPC_FLVR_POLICY_OFFSET (0)
+#define RPC_FLVR_MECH_OFFSET (4)
+#define RPC_FLVR_SVC_OFFSET (8)
-typedef __u32 ptlrpc_sec_flavor_t;
+#define MAKE_RPC_FLVR(policy, mech, svc) \
+ (((__u16)(policy) << RPC_FLVR_POLICY_OFFSET) | \
+ ((__u16)(mech) << RPC_FLVR_MECH_OFFSET) | \
+ ((__u16)(svc) << RPC_FLVR_SVC_OFFSET))
-/*
- * 8b (reserved) | 8b (flags)
- * 4b (reserved) | 4b (svc) | 4b (mech) | 4b (policy)
- */
-#define SEC_FLAVOR_POLICY_OFFSET (0)
-#define SEC_FLAVOR_MECH_OFFSET (4)
-#define SEC_FLAVOR_SVC_OFFSET (8)
-#define SEC_FLAVOR_RESERVE1_OFFSET (12)
-#define SEC_FLAVOR_FLAGS_OFFSET (16)
-
-#define SEC_MAKE_RPC_FLAVOR(policy, mech, svc) \
- (((__u32)(policy) << SEC_FLAVOR_POLICY_OFFSET) | \
- ((__u32)(mech) << SEC_FLAVOR_MECH_OFFSET) | \
- ((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET))
-
-#define SEC_MAKE_RPC_SUBFLAVOR(mech, svc) \
- ((__u32)(mech) | \
- ((__u32)(svc) << \
- (SEC_FLAVOR_SVC_OFFSET - SEC_FLAVOR_MECH_OFFSET)))
-
-#define SEC_FLAVOR_SUB(flavor) \
- ((((__u32)(flavor)) >> SEC_FLAVOR_MECH_OFFSET) & 0xFF)
-
-#define SEC_FLAVOR_POLICY(flavor) \
- ((((__u32)(flavor)) >> SEC_FLAVOR_POLICY_OFFSET) & 0xF)
-#define SEC_FLAVOR_MECH(flavor) \
- ((((__u32)(flavor)) >> SEC_FLAVOR_MECH_OFFSET) & 0xF)
-#define SEC_FLAVOR_SVC(flavor) \
- ((((__u32)(flavor)) >> SEC_FLAVOR_SVC_OFFSET) & 0xF)
-
-#define SEC_FLAVOR_RPC(f) \
- (((__u32) (f)) & ((1 << SEC_FLAVOR_RESERVE1_OFFSET) - 1))
+#define MAKE_RPC_SUBFLVR(mech, svc) \
+ ((__u16)(mech) | \
+ ((__u16)(svc) << (RPC_FLVR_SVC_OFFSET - RPC_FLVR_MECH_OFFSET)))
+
+#define RPC_FLVR_SUB(flavor) \
+ ((((__u16)(flavor)) >> RPC_FLVR_MECH_OFFSET) & 0xFF)
+
+#define RPC_FLVR_POLICY(flavor) \
+ ((((__u16)(flavor)) >> RPC_FLVR_POLICY_OFFSET) & 0xF)
+#define RPC_FLVR_MECH(flavor) \
+ ((((__u16)(flavor)) >> RPC_FLVR_MECH_OFFSET) & 0xF)
+#define RPC_FLVR_SVC(flavor) \
+ ((((__u16)(flavor)) >> RPC_FLVR_SVC_OFFSET) & 0xF)
/*
* gss subflavors
*/
-#define SPTLRPC_SUBFLVR_KRB5N \
- SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_NULL)
-#define SPTLRPC_SUBFLVR_KRB5A \
- SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_AUTH)
-#define SPTLRPC_SUBFLVR_KRB5I \
- SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_INTG)
-#define SPTLRPC_SUBFLVR_KRB5P \
- SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_PRIV)
+#define SPTLRPC_SUBFLVR_KRB5N \
+ MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_NULL)
+#define SPTLRPC_SUBFLVR_KRB5A \
+ MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_AUTH)
+#define SPTLRPC_SUBFLVR_KRB5I \
+ MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_INTG)
+#define SPTLRPC_SUBFLVR_KRB5P \
+ MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_PRIV)
/*
* "end user" flavors
*/
-#define SPTLRPC_FLVR_NULL \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_NULL, \
- SPTLRPC_MECH_NULL, \
- SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_PLAIN \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_PLAIN, \
- SPTLRPC_MECH_PLAIN, \
- SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_KRB5N \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS, \
- SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_KRB5A \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS, \
- SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_AUTH)
-#define SPTLRPC_FLVR_KRB5I \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS, \
- SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_INTG)
-#define SPTLRPC_FLVR_KRB5P \
- SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS, \
- SPTLRPC_MECH_GSS_KRB5, \
- SPTLRPC_SVC_PRIV)
-
-#define SPTLRPC_FLVR_INVALID (-1)
+#define SPTLRPC_FLVR_NULL \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_NULL, \
+ SPTLRPC_MECH_NULL, \
+ SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_PLAIN \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_PLAIN, \
+ SPTLRPC_MECH_PLAIN, \
+ SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_KRB5N \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS, \
+ SPTLRPC_MECH_GSS_KRB5, \
+ SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_KRB5A \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS, \
+ SPTLRPC_MECH_GSS_KRB5, \
+ SPTLRPC_SVC_AUTH)
+#define SPTLRPC_FLVR_KRB5I \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS, \
+ SPTLRPC_MECH_GSS_KRB5, \
+ SPTLRPC_SVC_INTG)
+#define SPTLRPC_FLVR_KRB5P \
+ MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS, \
+ SPTLRPC_MECH_GSS_KRB5, \
+ SPTLRPC_SVC_PRIV)
+
+#define SPTLRPC_FLVR_INVALID ((__u16) -1)
#define SPTLRPC_FLVR_DEFAULT SPTLRPC_FLVR_NULL
/*
- * flavor flags (maximum 8 flags)
+ * 32 bits wire flavor (msg->lm_secflvr), lower 12 bits is the rpc flavor,
+ * higher 20 bits is not defined right now.
*/
-#define SEC_FLAVOR_FL_BULK (1 << (0 + SEC_FLAVOR_FLAGS_OFFSET))
-#define SEC_FLAVOR_FL_USER (1 << (1 + SEC_FLAVOR_FLAGS_OFFSET))
+#define WIRE_FLVR_RPC(wflvr) (((__u16) (wflvr)) & 0x0FFF)
+
+static inline void rpc_flvr_set_svc(__u16 *flvr, __u16 svc)
+{
+ LASSERT(svc < SPTLRPC_SVC_MAX);
+ *flvr = MAKE_RPC_FLVR(RPC_FLVR_POLICY(*flvr),
+ RPC_FLVR_MECH(*flvr),
+ svc);
+}
+
-#define SEC_FLAVOR_HAS_BULK(flavor) \
- (((flavor) & SEC_FLAVOR_FL_BULK) != 0)
-#define SEC_FLAVOR_HAS_USER(flavor) \
- (((flavor) & SEC_FLAVOR_FL_USER) != 0)
+struct sptlrpc_flavor {
+ __u16 sf_rpc; /* rpc flavor */
+ __u8 sf_bulk_priv; /* bulk encrypt alg */
+ __u8 sf_bulk_csum; /* bulk checksum alg */
+ __u32 sf_flags; /* general flags */
+};
+enum lustre_sec_part {
+ LUSTRE_SP_CLI = 0,
+ LUSTRE_SP_MDT,
+ LUSTRE_SP_OST,
+ LUSTRE_SP_MGS,
+ LUSTRE_SP_ANY = 0xFF
+};
-struct sec_flavor_config {
- __u32 sfc_rpc_flavor; /* main rpc flavor */
- __u32 sfc_bulk_priv; /* bulk encryption algorithm */
- __u32 sfc_bulk_csum; /* bulk checksum algorithm */
- __u32 sfc_flags; /* extra flags */
+struct sptlrpc_rule {
+ __u32 sr_netid; /* LNET network ID */
+ __u8 sr_from; /* sec_part */
+ __u8 sr_to; /* sec_part */
+ __u16 sr_padding;
+ struct sptlrpc_flavor sr_flvr;
};
-enum lustre_part {
- LUSTRE_CLI = 0,
- LUSTRE_MDT,
- LUSTRE_OST,
- LUSTRE_MGC,
- LUSTRE_MGS,
+struct sptlrpc_rule_set {
+ int srs_nslot;
+ int srs_nrule;
+ struct sptlrpc_rule *srs_rules;
+};
+
+#define SPTLRPC_CONF_LOG_MAX (64)
+
+struct sptlrpc_conf_log {
+ __u32 scl_max; /* maximum rules # */
+ __u32 scl_nrule; /* rules # */
+ __u8 scl_part; /* which part am i */
+ __u8 scl_pad0;
+ __u16 scl_pad1;
+ __u32 scl_pad2;
+ struct sptlrpc_rule scl_rules[SPTLRPC_CONF_LOG_MAX];
};
+static inline void sptlrpc_rule_set_init(struct sptlrpc_rule_set *set)
+{
+ memset(set, 0, sizeof(*set));
+}
+
+void sptlrpc_rule_set_free(struct sptlrpc_rule_set *set);
+int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *set, int expand);
+int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *set,
+ struct sptlrpc_rule *rule,
+ int expand);
+int sptlrpc_rule_set_from_log(struct sptlrpc_rule_set *rset,
+ struct sptlrpc_conf_log *log);
+void sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+ enum lustre_sec_part from,
+ lnet_nid_t nid,
+ struct sptlrpc_flavor *flavor);
+void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *set);
+
+struct sptlrpc_conf_log *sptlrpc_conf_log_alloc(void);
+void sptlrpc_conf_log_free(struct sptlrpc_conf_log *log);
+int sptlrpc_conf_log_populate(struct sptlrpc_rule_set *gen,
+ struct sptlrpc_rule_set *tgt,
+ enum lustre_sec_part from,
+ enum lustre_sec_part to,
+ unsigned int fl_udesc,
+ struct sptlrpc_conf_log *log);
+struct sptlrpc_conf_log *sptlrpc_conf_log_extract(struct lustre_cfg *lcfg);
+void sptlrpc_conf_log_cleanup(struct sptlrpc_conf_log *log);
+void sptlrpc_conf_log_dump(struct sptlrpc_conf_log *log);
+
+const char *sptlrpc_part2name(enum lustre_sec_part part);
+enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd);
+
+int sptlrpc_cliobd_process_config(struct obd_device *obd,
+ struct lustre_cfg *lcfg);
+
/* The maximum length of security payload. 1024 is enough for Kerberos 5,
* and should be enough for other future mechanisms but not sure.
* Only used by pre-allocated request/reply pool.
*/
struct ptlrpc_sec * (*create_sec) (struct obd_import *imp,
struct ptlrpc_svc_ctx *ctx,
- __u32 flavor,
- unsigned long flags);
+ struct sptlrpc_flavor *flavor);
void (*destroy_sec) (struct ptlrpc_sec *sec);
/*
+ * notify to-be-dead
+ */
+ void (*kill_sec) (struct ptlrpc_sec *sec);
+
+ /*
* context
*/
struct ptlrpc_cli_ctx * (*lookup_ctx) (struct ptlrpc_sec *sec,
* misc
*/
int (*display) (struct ptlrpc_sec *sec,
- char *buf, int buflen);
+ struct seq_file *seq);
};
struct ptlrpc_sec_sops {
struct ptlrpc_sec_policy {
struct module *sp_owner;
char *sp_name;
- __u32 sp_policy; /* policy number */
+ __u16 sp_policy; /* policy number */
struct ptlrpc_sec_cops *sp_cops; /* client ops */
struct ptlrpc_sec_sops *sp_sops; /* server ops */
};
#define PTLRPC_SEC_FL_REVERSE 0x0001 /* reverse sec */
#define PTLRPC_SEC_FL_ROOTONLY 0x0002 /* treat everyone as root */
-#define PTLRPC_SEC_FL_PAG 0x0004 /* PAG mode */
+#define PTLRPC_SEC_FL_UDESC 0x0004 /* ship udesc */
#define PTLRPC_SEC_FL_BULK 0x0008 /* intensive bulk i/o expected */
+#define PTLRPC_SEC_FL_PAG 0x0010 /* PAG mode */
struct ptlrpc_sec {
struct ptlrpc_sec_policy *ps_policy;
atomic_t ps_refcount;
- __u32 ps_flavor; /* rpc flavor */
- unsigned long ps_flags; /* PTLRPC_SEC_FL_XX */
+ atomic_t ps_nctx; /* statistic only */
+ int ps_id; /* unique identifier */
+ struct sptlrpc_flavor ps_flvr; /* flavor */
+ enum lustre_sec_part ps_part;
+ unsigned int ps_dying:1;
struct obd_import *ps_import; /* owning import */
spinlock_t ps_lock; /* protect ccache */
- atomic_t ps_busy; /* busy count */
/*
* garbage collection
*/
static inline int sec_is_reverse(struct ptlrpc_sec *sec)
{
- return (sec->ps_flags & PTLRPC_SEC_FL_REVERSE);
+ return (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_REVERSE);
}
static inline int sec_is_rootonly(struct ptlrpc_sec *sec)
{
- return (sec->ps_flags & PTLRPC_SEC_FL_ROOTONLY);
+ return (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_ROOTONLY);
}
struct ptlrpc_bulk_sec_desc {
__u32 bsd_version;
- __u32 bsd_pad;
- __u32 bsd_csum_alg; /* checksum algorithm */
- __u32 bsd_priv_alg; /* encrypt algorithm */
+ __u8 bsd_csum_alg; /* checksum algorithm */
+ __u8 bsd_priv_alg; /* encrypt algorithm */
+ __u16 bsd_pad;
__u8 bsd_iv[16]; /* encrypt iv */
__u8 bsd_csum[0];
};
-const char * sptlrpc_bulk_csum_alg2name(__u32 csum_alg);
-const char * sptlrpc_bulk_priv_alg2name(__u32 priv_alg);
-__u32 sptlrpc_bulk_priv_alg2flags(__u32 priv_alg);
+const char * sptlrpc_bulk_csum_alg2name(__u8 csum_alg);
+const char * sptlrpc_bulk_priv_alg2name(__u8 priv_alg);
+__u32 sptlrpc_bulk_priv_alg2flags(__u8 priv_alg);
/*
* lprocfs
int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy);
int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy);
-__u32 sptlrpc_name2flavor(const char *name);
-char *sptlrpc_flavor2name(__u32 flavor);
+__u16 sptlrpc_name2rpcflavor(const char *name);
+const char *sptlrpc_rpcflavor2name(__u16 flavor);
+int sptlrpc_flavor2name(struct sptlrpc_flavor *sf, char *buf, int bufsize);
static inline
struct ptlrpc_sec_policy *sptlrpc_policy_get(struct ptlrpc_sec_policy *policy)
}
/*
+ * sec get/put
+ */
+struct ptlrpc_sec *sptlrpc_sec_get(struct ptlrpc_sec *sec);
+void sptlrpc_sec_put(struct ptlrpc_sec *sec);
+
+/*
* internal apis which only used by policy impelentation
*/
+int sptlrpc_get_next_secid(void);
void sptlrpc_sec_destroy(struct ptlrpc_sec *sec);
/*
/*
* exported higher interface of import & request
*/
-int sptlrpc_import_get_sec(struct obd_import *imp, struct ptlrpc_svc_ctx *svc_ctx,
- __u32 flavor, unsigned long flags);
-void sptlrpc_import_put_sec(struct obd_import *imp);
+int sptlrpc_import_sec_adapt(struct obd_import *imp,
+ struct ptlrpc_svc_ctx *ctx,
+ __u16 rpc_flavor);
+struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp);
+void sptlrpc_import_sec_put(struct obd_import *imp);
+
int sptlrpc_import_check_ctx(struct obd_import *imp);
+void sptlrpc_import_inval_all_ctx(struct obd_import *imp);
void sptlrpc_import_flush_root_ctx(struct obd_import *imp);
void sptlrpc_import_flush_my_ctx(struct obd_import *imp);
void sptlrpc_import_flush_all_ctx(struct obd_import *imp);
int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req);
void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode);
-int sptlrpc_parse_flavor(enum lustre_part from, enum lustre_part to,
- char *str, struct sec_flavor_config *conf);
+int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule);
/* gc */
void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec);
/* misc */
const char * sec2target_str(struct ptlrpc_sec *sec);
-int sptlrpc_lprocfs_rd(char *page, char **start, off_t off, int count,
- int *eof, void *data);
+int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev);
/*
* server side
SECSVC_DROP,
};
-int sptlrpc_target_export_check(struct obd_export *exp,
- struct ptlrpc_request *req);
int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req);
int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen);
int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req);
void sptlrpc_svc_ctx_decref(struct ptlrpc_request *req);
void sptlrpc_svc_ctx_invalidate(struct ptlrpc_request *req);
+int sptlrpc_target_export_check(struct obd_export *exp,
+ struct ptlrpc_request *req);
+void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
+ struct sptlrpc_rule_set *rset);
+
/*
* reverse context
*/
int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset);
/* bulk helpers (internal use only by policies) */
-int bulk_sec_desc_size(__u32 csum_alg, int request, int read);
+int bulk_sec_desc_size(__u8 csum_alg, int request, int read);
int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset);
int bulk_csum_cli_request(struct ptlrpc_bulk_desc *desc, int read,
struct upcall_cache_entry;
-struct mdt_setxid_perm {
+struct md_perm {
lnet_nid_t mp_nid;
__u32 mp_perm;
};
-struct mdt_identity {
+struct md_identity {
struct upcall_cache_entry *mi_uc_entry;
uid_t mi_uid;
gid_t mi_gid;
struct group_info *mi_ginfo;
int mi_nperms;
- struct mdt_setxid_perm *mi_perms;
-};
-
-struct rmtacl_upcall_data {
- uid_t aud_uid;
- gid_t aud_gid;
- char *aud_cmd;
-};
-
-struct mdt_rmtacl {
- uid_t ra_uid;
- gid_t ra_gid;
- __u32 ra_handle;
- char *ra_cmd;
- char *ra_buf;
+ struct md_perm *mi_perms;
};
struct upcall_cache_entry {
struct list_head ue_hash;
__u64 ue_key;
-// __u64 ue_primary;
-// struct group_info *ue_group_info;
atomic_t ue_refcount;
int ue_flags;
cfs_waitq_t ue_waitq;
cfs_time_t ue_acquire_expire;
cfs_time_t ue_expire;
union {
- struct mdt_identity identity;
- struct mdt_rmtacl acl;
+ struct md_identity identity;
} u;
};
struct md_object;
-typedef enum {
+enum {
UCRED_INVALID = -1,
UCRED_INIT = 0,
UCRED_OLD = 1,
- UCRED_NEW = 2,
-} ucred_t;
-
-#define SQUASH_NONE 0x00
-#define SQUASH_UID 0x01
-#define SQUASH_GID 0x02
+ UCRED_NEW = 2
+};
struct md_ucred {
- ucred_t mu_valid;
- __u32 mu_squash;
+ __u32 mu_valid;
__u32 mu_o_uid;
__u32 mu_o_gid;
__u32 mu_o_fsuid;
__u32 mu_cap;
__u32 mu_umask;
struct group_info *mu_ginfo;
- struct mdt_identity *mu_identity;
+ struct md_identity *mu_identity;
};
#define MD_CAPAINFO_MAX 5
int fo_fmd_max_num; /* per exp filter_mod_data */
int fo_fmd_max_age; /* jiffies to fmd expiry */
+ /* sptlrpc stuff */
+ rwlock_t fo_sptlrpc_lock;
+ struct sptlrpc_rule_set fo_sptlrpc_rset;
+
/* capability related */
unsigned int fo_fl_oss_capa;
struct list_head fo_capa_keys;
int cl_max_mds_cookiesize;
/* security configuration */
- struct sec_flavor_config cl_sec_conf;
+ struct sptlrpc_rule_set cl_sptlrpc_rset;
+ enum lustre_sec_part cl_sec_part;
//struct llog_canceld_ctxt *cl_llcd; /* it's included by obd_llog_ctxt */
void *cl_llcd_offset;
cfs_proc_dir_entry_t *mgs_proc_live;
};
-/* hah, upper limit 64 should be enough */
-#define N_NOSQUASH_NIDS 64
-struct rootsquash_info {
- uid_t rsi_uid;
- gid_t rsi_gid;
- int rsi_n_nosquash_nids;
- lnet_nid_t rsi_nosquash_nids[N_NOSQUASH_NIDS];
-};
-
struct mds_obd {
/* NB this field MUST be first */
struct obd_device_target mds_obt;
mds_fl_synced:1;
struct upcall_cache *mds_identity_cache;
- struct upcall_cache *mds_rmtacl_cache;
-
- /* root squash */
- struct rootsquash_info *mds_rootsquash_info;
/* for capability keys update */
struct lustre_capa_key *mds_capa_keys;
int (*o_connect)(const struct lu_env *env,
struct lustre_handle *conn, struct obd_device *src,
struct obd_uuid *cluuid, struct obd_connect_data *ocd);
- int (*o_reconnect)(struct obd_export *exp, struct obd_device *src,
+ int (*o_reconnect)(const struct lu_env *env,
+ struct obd_export *exp, struct obd_device *src,
struct obd_uuid *cluuid,
struct obd_connect_data *ocd);
int (*o_disconnect)(struct obd_export *exp);
struct ptlrpc_request **);
int (*m_getattr_name)(struct obd_export *, const struct lu_fid *,
struct obd_capa *, const char *, int, obd_valid,
- int, struct ptlrpc_request **);
+ int, __u32, struct ptlrpc_request **);
int (*m_intent_lock)(struct obd_export *, struct md_op_data *,
void *, int, struct lookup_intent *, int,
struct ptlrpc_request **,
int (*m_setxattr)(struct obd_export *, const struct lu_fid *,
struct obd_capa *, obd_valid, const char *,
- const char *, int, int, int,
+ const char *, int, int, int, __u32,
struct ptlrpc_request **);
int (*m_getxattr)(struct obd_export *, const struct lu_fid *,
renew_capa_cb_t cb);
int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *,
- struct obd_capa *, struct ptlrpc_request **);
+ struct obd_capa *, __u32,
+ struct ptlrpc_request **);
/*
* NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to
RETURN(rc);
}
-static inline int obd_reconnect(struct obd_export *exp,
+static inline int obd_reconnect(const struct lu_env *env,
+ struct obd_export *exp,
struct obd_device *obd,
struct obd_uuid *cluuid,
struct obd_connect_data *d)
OBD_CHECK_DT_OP(obd, reconnect, 0);
OBD_COUNTER_INCREMENT(obd, reconnect);
- rc = OBP(obd, reconnect)(exp, obd, cluuid, d);
+ rc = OBP(obd, reconnect)(env, exp, obd, cluuid, d);
/* check that only subset is granted */
LASSERT(ergo(d != NULL,
(d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
static inline int md_getattr_name(struct obd_export *exp,
const struct lu_fid *fid, struct obd_capa *oc,
const char *name, int namelen,
- obd_valid valid, int ea_size,
+ obd_valid valid, int ea_size, __u32 suppgid,
struct ptlrpc_request **request)
{
int rc;
EXP_CHECK_MD_OP(exp, getattr_name);
EXP_MD_COUNTER_INCREMENT(exp, getattr_name);
rc = MDP(exp->exp_obd, getattr_name)(exp, fid, oc, name, namelen,
- valid, ea_size, request);
+ valid, ea_size, suppgid, request);
RETURN(rc);
}
const struct lu_fid *fid, struct obd_capa *oc,
obd_valid valid, const char *name,
const char *input, int input_size,
- int output_size, int flags,
+ int output_size, int flags, __u32 suppgid,
struct ptlrpc_request **request)
{
ENTRY;
EXP_MD_COUNTER_INCREMENT(exp, setxattr);
RETURN(MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input,
input_size, output_size, flags,
- request));
+ suppgid, request));
}
static inline int md_getxattr(struct obd_export *exp,
static inline int md_get_remote_perm(struct obd_export *exp,
const struct lu_fid *fid,
- struct obd_capa *oc,
+ struct obd_capa *oc, __u32 suppgid,
struct ptlrpc_request **request)
{
ENTRY;
EXP_CHECK_MD_OP(exp, get_remote_perm);
EXP_MD_COUNTER_INCREMENT(exp, get_remote_perm);
- RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, request));
+ RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, suppgid,
+ request));
}
static inline int md_renew_capa(struct obd_export *exp, struct obd_capa *ocapa,
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
static void destroy_import(struct obd_import *imp)
{
/* drop security policy instance after all rpc finished/aborted
- * to let all busy credentials be released.
- */
+ * to let all busy contexts be released. */
class_import_get(imp);
class_destroy_import(imp);
- sptlrpc_import_put_sec(imp);
+ sptlrpc_import_sec_put(imp);
class_import_put(imp);
}
sema_init(&cli->cl_sem, 1);
sema_init(&cli->cl_mgc_sem, 1);
- cli->cl_sec_conf.sfc_rpc_flavor = SPTLRPC_FLVR_NULL;
- cli->cl_sec_conf.sfc_bulk_csum = BULK_CSUM_ALG_NULL;
- cli->cl_sec_conf.sfc_bulk_priv = BULK_PRIV_ALG_NULL;
- cli->cl_sec_conf.sfc_flags = 0;
+ sptlrpc_rule_set_init(&cli->cl_sptlrpc_rset);
+ cli->cl_sec_part = LUSTRE_SP_ANY;
cli->cl_conn_count = 0;
memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
int client_obd_cleanup(struct obd_device *obddev)
{
ENTRY;
+ sptlrpc_rule_set_free(&obddev->u.cli.cl_sptlrpc_rset);
ldlm_put_ref(obddev->obd_force);
RETURN(0);
}
if (rc != 0)
GOTO(out_ldlm, rc);
- rc = sptlrpc_import_get_sec(imp, NULL, cli->cl_sec_conf.sfc_rpc_flavor,
- cli->cl_sec_conf.sfc_flags);
- if (rc)
- GOTO(out_ldlm, rc);
-
ocd = &imp->imp_connect_data;
if (data) {
*ocd = *data;
&conn, target, &cluuid, data);
}
} else {
- rc = obd_reconnect(export, target, &cluuid, data);
+ rc = obd_reconnect(req->rq_svc_thread->t_env,
+ export, target, &cluuid, data);
}
if (rc)
GOTO(out, rc);
/* destroyed import can be still referenced in ctxt */
obd_set_info_async(export, strlen(KEY_REVIMP_UPD),
KEY_REVIMP_UPD, 0, NULL, NULL);
+
+ /* in some recovery senarios, previous ctx init rpc handled
+ * in sptlrpc_target_export_check() might be used to install
+ * a reverse ctx in this reverse import, and later OBD_CONNECT
+ * using the same gss ctx could reach here and following new
+ * reverse import. note all reverse ctx in new/old import are
+ * actually based on the same gss ctx. so we invalidate ctx
+ * here before destroy import, otherwise flush old import will
+ * lead to remote reverse ctx be destroied, thus the reverse
+ * ctx of new import will lost its peer.
+ * there might be a better way to deal with this???
+ */
+ sptlrpc_import_inval_all_ctx(export->exp_imp_reverse);
+
destroy_import(export->exp_imp_reverse);
}
lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_NEXT_VER);
}
- rc = sptlrpc_import_get_sec(revimp, req->rq_svc_ctx,
- req->rq_sec_flavor, 0);
+ rc = sptlrpc_import_sec_adapt(revimp, req->rq_svc_ctx,
+ req->rq_flvr.sf_rpc);
if (rc) {
CERROR("Failed to get sec for reverse import: %d\n", rc);
export->exp_imp_reverse = NULL;
static int ldlm_callback_reply(struct ptlrpc_request *req, int rc)
{
+ if (req->rq_no_reply)
+ return 0;
+
req->rq_status = rc;
if (req->rq_reply_state == NULL) {
rc = lustre_pack_reply(req, 1, NULL, NULL);
MODULES := lustre llite_lloop
lustre-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o
lustre-objs += llite_fid.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o
-lustre-objs += xattr.o remote_perm.o llite_capa.o
+lustre-objs += xattr.o remote_perm.o llite_rmtacl.o llite_capa.o
lustre-objs += rw26.o super25.o
llite_lloop-objs := lloop.o
oc = ll_mdscapa_get(inode);
rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode), oc,
filename, namelen, OBD_MD_FLID, 0,
- &request);
+ ll_i2suppgid(inode), &request);
capa_put(oc);
if (rc < 0) {
CDEBUG(D_INFO, "md_getattr_name: %d\n", rc);
}
case LL_IOC_FLUSHCTX:
RETURN(ll_flush_ctx(inode));
- case LL_IOC_GETFACL: {
- struct rmtacl_ioctl_data ioc;
-
- if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
- RETURN(-EFAULT);
-
- RETURN(ll_ioctl_getfacl(inode, &ioc));
- }
- case LL_IOC_SETFACL: {
- struct rmtacl_ioctl_data ioc;
-
- if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
- RETURN(-EFAULT);
+#ifdef CONFIG_FS_POSIX_ACL
+ case LL_IOC_RMTACL: {
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+ inode == inode->i_sb->s_root->d_inode) {
+ struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ int rc;
- RETURN(ll_ioctl_setfacl(inode, &ioc));
+ LASSERT(fd != NULL);
+ rc = rct_add(&sbi->ll_rct, cfs_curproc_pid(), arg);
+ if (!rc)
+ fd->fd_flags |= LL_FILE_RMTACL;
+ RETURN(rc);
+ } else
+ RETURN(0);
}
+#endif
default:
RETURN(obd_iocontrol(cmd, sbi->ll_dt_exp,0,NULL,(void *)arg));
}
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
inode->i_generation, inode);
- /* don't do anything for / */
- if (inode->i_sb->s_root == file->f_dentry)
- RETURN(0);
+#ifdef CONFIG_FS_POSIX_ACL
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+ inode == inode->i_sb->s_root->d_inode) {
+ struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+
+ LASSERT(fd != NULL);
+ if (unlikely(fd->fd_flags & LL_FILE_RMTACL)) {
+ fd->fd_flags &= ~LL_FILE_RMTACL;
+ rct_del(&sbi->ll_rct, cfs_curproc_pid());
+ et_search_free(&sbi->ll_et, cfs_curproc_pid());
+ }
+ }
+#endif
ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, 1);
fd = LUSTRE_FPRIVATE(file);
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
inode->i_generation, inode, file->f_flags);
- /* don't do anything for / */
- if (inode->i_sb->s_root == file->f_dentry)
- RETURN(0);
-
#ifdef HAVE_VFS_INTENT_PATCHES
it = file->f_it;
#else
oc = ll_mdscapa_get(inode);
rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode),
oc, filename, strlen(filename) + 1,
- OBD_MD_FLEASIZE | OBD_MD_FLDIREA, lmmsize, &req);
+ OBD_MD_FLEASIZE | OBD_MD_FLDIREA, lmmsize,
+ ll_i2suppgid(inode), &req);
capa_put(oc);
if (rc < 0) {
CDEBUG(D_INFO, "md_getattr_name failed "
*/
case LL_IOC_FLUSHCTX:
RETURN(ll_flush_ctx(inode));
- case LL_IOC_GETFACL: {
- struct rmtacl_ioctl_data ioc;
-
- if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
- RETURN(-EFAULT);
-
- RETURN(ll_ioctl_getfacl(inode, &ioc));
- }
- case LL_IOC_SETFACL: {
- struct rmtacl_ioctl_data ioc;
-
- if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
- RETURN(-EFAULT);
-
- RETURN(ll_ioctl_setfacl(inode, &ioc));
- }
default: {
int err;
# include <linux/fs.h>
#ifdef HAVE_XATTR_ACL
# include <linux/xattr_acl.h>
-#endif
+#endif /* HAVE_XATTR_ACL */
#ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
# include <linux/posix_acl_xattr.h>
-#endif
-#endif
+#endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+#endif /* CONFIG_FS_POSIX_ACL */
#include <lustre_debug.h>
#include <lustre_ver.h>
#include <lustre_disk.h> /* for s2sbi */
+#include <lustre_eacl.h>
#ifndef FMODE_EXEC
#define FMODE_EXEC 0
#define LL_SBI_LOCALFLOCK 0x200 /* Local flocks support by kernel */
#define LL_SBI_LRU_RESIZE 0x400 /* lru resize support */
+#define RCE_HASHES 32
+
+struct rmtacl_ctl_entry {
+ struct list_head rce_list;
+ pid_t rce_key; /* hash key */
+ int rce_ops; /* acl operation type */
+};
+
+struct rmtacl_ctl_table {
+ spinlock_t rct_lock;
+ struct list_head rct_entries[RCE_HASHES];
+};
+
+#define EE_HASHES 32
+
+struct eacl_entry {
+ struct list_head ee_list;
+ pid_t ee_key; /* hash key */
+ struct lu_fid ee_fid;
+ int ee_type; /* ACL type for ACCESS or DEFAULT */
+ ext_acl_xattr_header *ee_acl;
+};
+
+struct eacl_table {
+ spinlock_t et_lock;
+ struct list_head et_entries[EE_HASHES];
+};
+
struct ll_sb_info {
struct list_head ll_list;
/* this protects pglist and ra_info. It isn't safe to
dev_t ll_sdev_orig; /* save s_dev before assign for
* clustred nfs */
+ struct rmtacl_ctl_table ll_rct;
+ struct eacl_table ll_et;
};
#define LL_DEFAULT_MAX_RW_CHUNK (32 * 1024 * 1024)
obd_id hash;
};
+__u32 ll_i2suppgid(struct inode *i);
void ll_i2gids(__u32 *suppgids, struct inode *i1,struct inode *i2);
#define LLAP_MAGIC 98764321
int ll_obd_statfs(struct inode *inode, void *arg);
int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
int ll_process_config(struct lustre_cfg *lcfg);
-int ll_ioctl_getfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc);
-int ll_ioctl_setfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc);
struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
struct inode *i1, struct inode *i2,
const char *name, int namelen,
void ll_clear_inode_capas(struct inode *inode);
void ll_print_capa_stat(struct ll_sb_info *sbi);
+/* llite/llite_rmtacl.c */
+#ifdef CONFIG_FS_POSIX_ACL
+obd_valid rce_ops2valid(int ops);
+struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key);
+int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops);
+int rct_del(struct rmtacl_ctl_table *rct, pid_t key);
+void rct_init(struct rmtacl_ctl_table *rct);
+void rct_fini(struct rmtacl_ctl_table *rct);
+
+void ee_free(struct eacl_entry *ee);
+int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
+ ext_acl_xattr_header *header);
+struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
+ struct lu_fid *fid, int type);
+void et_search_free(struct eacl_table *et, pid_t key);
+void et_init(struct eacl_table *et);
+void et_fini(struct eacl_table *et);
+#endif
+
/* llite ioctl register support rountine */
#ifdef __KERNEL__
enum llioc_iter {
RETURN(rc);
}
-static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
- uid_t nllu, gid_t nllg)
+static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
{
struct inode *root = 0;
struct ll_sb_info *sbi = ll_s2sbi(sb);
data->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
data->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
}
- data->ocd_nllu = nllu;
- data->ocd_nllg = nllg;
err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, data);
if (err == -EBUSY) {
GOTO(out_root, err);
}
+#ifdef CONFIG_FS_POSIX_ACL
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
+ rct_init(&sbi->ll_rct);
+ et_init(&sbi->ll_et);
+ }
+#endif
+
checksum = sbi->ll_flags & LL_SBI_CHECKSUM;
err = obd_set_info_async(sbi->ll_dt_exp, strlen("checksum"),"checksum",
sizeof(checksum), &checksum, NULL);
struct ll_sb_info *sbi = ll_s2sbi(sb);
ENTRY;
+#ifdef CONFIG_FS_POSIX_ACL
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
+ et_fini(&sbi->ll_et);
+ rct_fini(&sbi->ll_rct);
+ }
+#endif
+
obd_cancel_unused(sbi->ll_dt_exp, NULL, 0, NULL);
ll_close_thread_shutdown(sbi->ll_lcq);
sprintf(md, "%s-%s", lprof->lp_md, ll_instance);
/* connections, registrations, sb setup */
- err = client_common_fill_super(sb, md, dt,
- lsi->lsi_lmd->lmd_nllu,
- lsi->lsi_lmd->lmd_nllg);
+ err = client_common_fill_super(sb, md, dt);
out_free:
if (md)
capa_put(op_data->op_capa2);
OBD_FREE_PTR(op_data);
}
-
-int ll_ioctl_getfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ptlrpc_request *req = NULL;
- struct mdt_body *body;
- char *cmd, *buf;
- struct obd_capa *oc;
- int rc, buflen;
- ENTRY;
-
- if (!(sbi->ll_flags & LL_SBI_RMT_CLIENT))
- RETURN(-EBADE);
-
- LASSERT(ioc->cmd && ioc->cmd_len && ioc->res && ioc->res_len);
-
- OBD_ALLOC(cmd, ioc->cmd_len);
- if (!cmd)
- RETURN(-ENOMEM);
- if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
- GOTO(out, rc = -EFAULT);
-
- oc = ll_mdscapa_get(inode);
- rc = md_getxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
- OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
- ioc->cmd_len, ioc->res_len, 0, &req);
- capa_put(oc);
- if (rc < 0) {
- CERROR("mdc_getxattr %s [%s] failed: %d\n",
- XATTR_NAME_LUSTRE_ACL, cmd, rc);
- GOTO(out, rc);
- }
-
- body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
- LASSERT(body);
-
- buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF);
- LASSERT(buflen <= ioc->res_len);
- buf = lustre_msg_string(req->rq_repmsg, REPLY_REC_OFF + 1, ioc->res_len);
- LASSERT(buf);
- if (copy_to_user(ioc->res, buf, buflen))
- GOTO(out, rc = -EFAULT);
- EXIT;
-out:
- if (req)
- ptlrpc_req_finished(req);
- OBD_FREE(cmd, ioc->cmd_len);
- return rc;
-}
-
-int ll_ioctl_setfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ptlrpc_request *req = NULL;
- char *cmd, *buf;
- struct obd_capa *oc;
- int buflen, rc;
- ENTRY;
-
- if (!(sbi->ll_flags & LL_SBI_RMT_CLIENT))
- RETURN(-EBADE);
-
- if (!(sbi->ll_flags & LL_SBI_ACL))
- RETURN(-EOPNOTSUPP);
-
- LASSERT(ioc->cmd && ioc->cmd_len && ioc->res && ioc->res_len);
-
- OBD_ALLOC(cmd, ioc->cmd_len);
- if (!cmd)
- RETURN(-ENOMEM);
- if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
- GOTO(out, rc = -EFAULT);
-
- oc = ll_mdscapa_get(inode);
- rc = md_setxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
- OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
- ioc->cmd_len, ioc->res_len, 0, &req);
- capa_put(oc);
- if (rc) {
- CERROR("mdc_setxattr %s [%s] failed: %d\n",
- XATTR_NAME_LUSTRE_ACL, cmd, rc);
- GOTO(out, rc);
- }
-
- buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF);
- LASSERT(buflen <= ioc->res_len);
- buf = lustre_msg_string(req->rq_repmsg, REPLY_REC_OFF, ioc->res_len);
- LASSERT(buf);
- if (copy_to_user(ioc->res, buf, buflen))
- GOTO(out, rc = -EFAULT);
- EXIT;
-out:
- if (req)
- ptlrpc_req_finished(req);
- OBD_FREE(cmd, ioc->cmd_len);
- return rc;
-}
dir->i_ino, PFID(ll_inode2fid(dir)));
rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(dir), NULL,
- dotdot, strlen(dotdot) + 1, 0, 0, &req);
+ dotdot, strlen(dotdot) + 1, 0, 0,
+ ll_i2suppgid(dir), &req);
if (rc) {
CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
RETURN(ERR_PTR(rc));
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * lustre/llite/llite_rmtacl.c
+ * Lustre Remote User Access Control List.
+ * Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ * Copyright (c) 2004-2007 Cluster File Systems, Inc.
+ *
+ * This file is part of Lustre, http://www.lustre.org.
+ *
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * Lustre is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#ifdef CONFIG_FS_POSIX_ACL
+
+#include <lustre_lite.h>
+#include "llite_internal.h"
+
+static inline __u32 rce_hashfunc(uid_t id)
+{
+ return id & (RCE_HASHES - 1);
+}
+
+static inline __u32 ee_hashfunc(uid_t id)
+{
+ return id & (EE_HASHES - 1);
+}
+
+obd_valid rce_ops2valid(int ops)
+{
+ switch (ops) {
+ case RMT_LSETFACL:
+ return OBD_MD_FLRMTLSETFACL;
+ case RMT_LGETFACL:
+ return OBD_MD_FLRMTLGETFACL;
+ case RMT_RSETFACL:
+ return OBD_MD_FLRMTRSETFACL;
+ case RMT_RGETFACL:
+ return OBD_MD_FLRMTRGETFACL;
+ default:
+ return 0;
+ }
+}
+
+static struct rmtacl_ctl_entry *rce_alloc(pid_t key, int ops)
+{
+ struct rmtacl_ctl_entry *rce;
+
+ OBD_ALLOC_PTR(rce);
+ if (!rce)
+ return NULL;
+
+ CFS_INIT_LIST_HEAD(&rce->rce_list);
+ rce->rce_key = key;
+ rce->rce_ops = ops;
+
+ return rce;
+}
+
+static void rce_free(struct rmtacl_ctl_entry *rce)
+{
+ if (!list_empty(&rce->rce_list))
+ list_del(&rce->rce_list);
+
+ OBD_FREE_PTR(rce);
+}
+
+static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct,
+ pid_t key)
+{
+ struct rmtacl_ctl_entry *rce;
+ struct list_head *head = &rct->rct_entries[rce_hashfunc(key)];
+
+ list_for_each_entry(rce, head, rce_list)
+ if (rce->rce_key == key)
+ return rce;
+
+ return NULL;
+}
+
+struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key)
+{
+ struct rmtacl_ctl_entry *rce;
+
+ spin_lock(&rct->rct_lock);
+ rce = __rct_search(rct, key);
+ spin_unlock(&rct->rct_lock);
+ return rce;
+}
+
+int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops)
+{
+ struct rmtacl_ctl_entry *rce, *e;
+
+ rce = rce_alloc(key, ops);
+ if (rce == NULL)
+ return -ENOMEM;
+
+ spin_lock(&rct->rct_lock);
+ e = __rct_search(rct, key);
+ if (unlikely(e != NULL)) {
+ CWARN("Unexpected stale rmtacl_entry found: "
+ "[key: %d] [ops: %d]\n", (int)key, ops);
+ rce_free(e);
+ }
+ list_add_tail(&rce->rce_list, &rct->rct_entries[rce_hashfunc(key)]);
+ spin_unlock(&rct->rct_lock);
+
+ return 0;
+}
+
+int rct_del(struct rmtacl_ctl_table *rct, pid_t key)
+{
+ struct rmtacl_ctl_entry *rce;
+
+ spin_lock(&rct->rct_lock);
+ rce = __rct_search(rct, key);
+ if (rce)
+ rce_free(rce);
+ spin_unlock(&rct->rct_lock);
+
+ return rce ? 0 : -ENOENT;
+}
+
+void rct_init(struct rmtacl_ctl_table *rct)
+{
+ int i;
+
+ spin_lock_init(&rct->rct_lock);
+ for (i = 0; i < RCE_HASHES; i++)
+ CFS_INIT_LIST_HEAD(&rct->rct_entries[i]);
+}
+
+void rct_fini(struct rmtacl_ctl_table *rct)
+{
+ struct rmtacl_ctl_entry *rce;
+ int i;
+
+ spin_lock(&rct->rct_lock);
+ for (i = 0; i < RCE_HASHES; i++)
+ while (!list_empty(&rct->rct_entries[i])) {
+ rce = list_entry(rct->rct_entries[i].next,
+ struct rmtacl_ctl_entry, rce_list);
+ rce_free(rce);
+ }
+ spin_unlock(&rct->rct_lock);
+}
+
+
+static struct eacl_entry *ee_alloc(pid_t key, struct lu_fid *fid, int type,
+ ext_acl_xattr_header *header)
+{
+ struct eacl_entry *ee;
+
+ OBD_ALLOC_PTR(ee);
+ if (!ee)
+ return NULL;
+
+ CFS_INIT_LIST_HEAD(&ee->ee_list);
+ ee->ee_key = key;
+ ee->ee_fid = *fid;
+ ee->ee_type = type;
+ ee->ee_acl = header;
+
+ return ee;
+}
+
+void ee_free(struct eacl_entry *ee)
+{
+ if (!list_empty(&ee->ee_list))
+ list_del(&ee->ee_list);
+
+ if (ee->ee_acl)
+ lustre_ext_acl_xattr_free(ee->ee_acl);
+
+ OBD_FREE_PTR(ee);
+}
+
+static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key,
+ struct lu_fid *fid, int type)
+{
+ struct eacl_entry *ee;
+ struct list_head *head = &et->et_entries[ee_hashfunc(key)];
+
+ LASSERT(fid != NULL);
+ list_for_each_entry(ee, head, ee_list)
+ if (ee->ee_key == key) {
+ if (lu_fid_eq(&ee->ee_fid, fid) &&
+ ee->ee_type == type) {
+ list_del_init(&ee->ee_list);
+ return ee;
+ }
+ }
+
+ return NULL;
+}
+
+struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
+ struct lu_fid *fid, int type)
+{
+ struct eacl_entry *ee;
+
+ spin_lock(&et->et_lock);
+ ee = __et_search_del(et, key, fid, type);
+ spin_unlock(&et->et_lock);
+ return ee;
+}
+
+void et_search_free(struct eacl_table *et, pid_t key)
+{
+ struct eacl_entry *ee, *next;
+ struct list_head *head = &et->et_entries[ee_hashfunc(key)];
+
+ spin_lock(&et->et_lock);
+ list_for_each_entry_safe(ee, next, head, ee_list)
+ if (ee->ee_key == key)
+ ee_free(ee);
+
+ spin_unlock(&et->et_lock);
+}
+
+int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
+ ext_acl_xattr_header *header)
+{
+ struct eacl_entry *ee, *e;
+
+ ee = ee_alloc(key, fid, type, header);
+ if (ee == NULL)
+ return -ENOMEM;
+
+ spin_lock(&et->et_lock);
+ e = __et_search_del(et, key, fid, type);
+ if (unlikely(e != NULL)) {
+ CWARN("Unexpected stale eacl_entry found: "
+ "[key: %d] [fid: "DFID"] [type: %d]\n",
+ (int)key, PFID(fid), type);
+ ee_free(e);
+ }
+ list_add_tail(&ee->ee_list, &et->et_entries[ee_hashfunc(key)]);
+ spin_unlock(&et->et_lock);
+
+ return 0;
+}
+
+void et_init(struct eacl_table *et)
+{
+ int i;
+
+ spin_lock_init(&et->et_lock);
+ for (i = 0; i < EE_HASHES; i++)
+ CFS_INIT_LIST_HEAD(&et->et_entries[i]);
+}
+
+void et_fini(struct eacl_table *et)
+{
+ struct eacl_entry *ee;
+ int i;
+
+ spin_lock(&et->et_lock);
+ for (i = 0; i < EE_HASHES; i++)
+ while (!list_empty(&et->et_entries[i])) {
+ ee = list_entry(et->et_entries[i].next,
+ struct eacl_entry, ee_list);
+ ee_free(ee);
+ }
+ spin_unlock(&et->et_lock);
+}
+
+#endif
RETURN(0);
}
+__u32 ll_i2suppgid(struct inode *i)
+{
+ if (in_group_p(i->i_gid))
+ return (__u32)i->i_gid;
+ else
+ return (__u32)(-1);
+}
+
/* Pack the required supplementary groups into the supplied groups array.
* If we don't need to use the groups from the target inode(s) then we
* instead pack one or more groups from the user's supplementary group
* array in case it might be useful. Not needed if doing an MDS-side upcall. */
void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
{
+#if 0
int i;
+#endif
LASSERT(i1 != NULL);
LASSERT(suppgids != NULL);
- if (in_group_p(i1->i_gid))
- suppgids[0] = i1->i_gid;
- else
- suppgids[0] = -1;
+ suppgids[0] = ll_i2suppgid(i1);
- if (i2) {
- if (in_group_p(i2->i_gid))
- suppgids[1] = i2->i_gid;
+ if (i2)
+ suppgids[1] = ll_i2suppgid(i2);
else
suppgids[1] = -1;
- } else {
- suppgids[1] = -1;
- }
+#if 0
for (i = 0; i < current_ngroups; i++) {
if (suppgids[0] == -1) {
if (current_groups[i] != suppgids[1])
}
break;
}
+#endif
}
static void ll_d_add(struct dentry *de, struct inode *inode)
}
oc = ll_mdscapa_get(inode);
- rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode), oc, &req);
+ rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+ ll_i2suppgid(inode), &req);
capa_put(oc);
if (rc) {
up(&lli->lli_rmtperm_sem);
static
int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
{
- if (((xattr_type == XATTR_ACL_ACCESS_T) ||
- (xattr_type == XATTR_ACL_DEFAULT_T)) &&
- (!(sbi->ll_flags & LL_SBI_ACL) ||
- (sbi->ll_flags & LL_SBI_RMT_CLIENT)))
+ if ((xattr_type == XATTR_ACL_ACCESS_T ||
+ xattr_type == XATTR_ACL_DEFAULT_T) &&
+ !(sbi->ll_flags & LL_SBI_ACL))
return -EOPNOTSUPP;
if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
struct ptlrpc_request *req;
int xattr_type, rc;
struct obd_capa *oc;
+ posix_acl_xattr_header *new_value = NULL;
+ struct rmtacl_ctl_entry *rce = NULL;
+ ext_acl_xattr_header *acl = NULL;
+ const char *pv = value;
ENTRY;
xattr_type = get_xattr_type(name);
(xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
RETURN(0);
+#ifdef CONFIG_FS_POSIX_ACL
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+ (xattr_type == XATTR_ACL_ACCESS_T ||
+ xattr_type == XATTR_ACL_DEFAULT_T)) {
+ rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
+ if (rce == NULL ||
+ (rce->rce_ops != RMT_LSETFACL &&
+ rce->rce_ops != RMT_RSETFACL))
+ RETURN(-EOPNOTSUPP);
+
+ if (rce->rce_ops == RMT_LSETFACL) {
+ struct eacl_entry *ee;
+
+ ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(),
+ ll_inode2fid(inode), xattr_type);
+ LASSERT(ee != NULL);
+ if (valid & OBD_MD_FLXATTR) {
+ acl = lustre_acl_xattr_merge2ext(
+ (posix_acl_xattr_header *)value,
+ size, ee->ee_acl);
+ if (IS_ERR(acl)) {
+ ee_free(ee);
+ RETURN(PTR_ERR(acl));
+ }
+ size = CFS_ACL_XATTR_SIZE(\
+ le32_to_cpu(acl->a_count), \
+ ext_acl_xattr);
+ pv = (const char *)acl;
+ }
+ ee_free(ee);
+ } else if (rce->rce_ops == RMT_RSETFACL) {
+ size = lustre_posix_acl_xattr_filter(
+ (posix_acl_xattr_header *)value,
+ size, &new_value);
+ if (unlikely(size < 0))
+ RETURN(size);
+
+ pv = (const char *)new_value;
+ } else
+ RETURN(-EOPNOTSUPP);
+
+ valid |= rce_ops2valid(rce->rce_ops);
+ }
+#endif
oc = ll_mdscapa_get(inode);
- rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
- value, size, 0, flags, &req);
+ rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+ valid, name, pv, size, 0, flags, ll_i2suppgid(inode),
+ &req);
capa_put(oc);
+#ifdef CONFIG_FS_POSIX_ACL
+ if (new_value != NULL)
+ lustre_posix_acl_xattr_free(new_value, size);
+ if (acl != NULL)
+ lustre_ext_acl_xattr_free(acl);
+#endif
if (rc) {
if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
LCONSOLE_INFO("Disabling user_xattr feature because "
int xattr_type, rc;
void *xdata;
struct obd_capa *oc;
+ struct rmtacl_ctl_entry *rce = NULL;
ENTRY;
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
if (rc)
RETURN(rc);
+#ifdef CONFIG_FS_POSIX_ACL
+ if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+ (xattr_type == XATTR_ACL_ACCESS_T ||
+ xattr_type == XATTR_ACL_DEFAULT_T)) {
+ rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
+ if (rce == NULL ||
+ (rce->rce_ops != RMT_LSETFACL &&
+ rce->rce_ops != RMT_LGETFACL &&
+ rce->rce_ops != RMT_RSETFACL &&
+ rce->rce_ops != RMT_RGETFACL))
+ RETURN(-EOPNOTSUPP);
+ }
+#endif
+
/* posix acl is under protection of LOOKUP lock. when calling to this,
* we just have path resolution to the target inode, so we have great
* chance that cached ACL is uptodate.
*/
#ifdef CONFIG_FS_POSIX_ACL
- if (xattr_type == XATTR_ACL_ACCESS_T) {
+ if (xattr_type == XATTR_ACL_ACCESS_T &&
+ !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
struct ll_inode_info *lli = ll_i2info(inode);
struct posix_acl *acl;
do_getxattr:
oc = ll_mdscapa_get(inode);
- rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
- NULL, 0, size, 0, &req);
+ rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+ valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
+ name, NULL, 0, size, 0, &req);
capa_put(oc);
if (rc) {
if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
GOTO(out, rc = -EFAULT);
}
+#ifdef CONFIG_FS_POSIX_ACL
+ if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
+ ext_acl_xattr_header *acl;
+
+ acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
+ body->eadatasize);
+ if (IS_ERR(acl))
+ GOTO(out, rc = PTR_ERR(acl));
+
+ rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
+ xattr_type, acl);
+ if (unlikely(rc < 0)) {
+ lustre_ext_acl_xattr_free(acl);
+ GOTO(out, rc);
+ }
+ }
+
+ if (xattr_type == XATTR_ACL_ACCESS_T && !body->eadatasize)
+ GOTO(out, rc = -ENODATA);
+#endif
LASSERT(buffer);
memcpy(buffer, xdata, body->eadatasize);
rc = body->eadatasize;
+ EXIT;
out:
ptlrpc_req_finished(req);
- RETURN(rc);
+ return rc;
}
ssize_t ll_getxattr(struct dentry *dentry, const char *name,
static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
struct obd_capa *oc, obd_valid valid, const char *name,
const char *input, int input_size, int output_size,
- int flags, struct ptlrpc_request **request)
+ int flags, __u32 suppgid,
+ struct ptlrpc_request **request)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
RETURN(PTR_ERR(tgt_exp));
rc = md_setxattr(tgt_exp, fid, oc, valid, name,
- input, input_size, output_size, flags, request);
+ input, input_size, output_size, flags, suppgid,
+ request);
RETURN(rc);
}
static int
lmv_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
struct obd_capa *oc, const char *filename, int namelen,
- obd_valid valid, int ea_size, struct ptlrpc_request **request)
+ obd_valid valid, int ea_size, __u32 suppgid,
+ struct ptlrpc_request **request)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
namelen, filename, PFID(fid), PFID(&rid));
rc = md_getattr_name(tgt_exp, &rid, oc, filename, namelen, valid,
- ea_size, request);
+ ea_size, suppgid, request);
if (rc == 0) {
body = lustre_msg_buf((*request)->rq_repmsg,
REQ_REC_OFF, sizeof(*body));
rc = md_getattr_name(tgt_exp, &rid, NULL, NULL, 1,
valid | OBD_MD_FLCROSSREF,
- ea_size, &req);
+ ea_size, suppgid, &req);
ptlrpc_req_finished(*request);
*request = req;
}
static int lmv_get_remote_perm(struct obd_export *exp,
const struct lu_fid *fid,
- struct obd_capa *oc,
+ struct obd_capa *oc, __u32 suppgid,
struct ptlrpc_request **request)
{
struct obd_device *obd = exp->exp_obd;
if (IS_ERR(tgt_exp))
RETURN(PTR_ERR(tgt_exp));
- rc = md_get_remote_perm(tgt_exp, fid, oc, request);
+ rc = md_get_remote_perm(tgt_exp, fid, oc, suppgid, request);
RETURN(rc);
}
{ "mds_conn_uuid", lprocfs_rd_conn_uuid, 0, 0 },
{ "max_rpcs_in_flight", mdc_rd_max_rpcs_in_flight,
mdc_wr_max_rpcs_in_flight, 0 },
- { "sptlrpc", sptlrpc_lprocfs_rd, 0, 0 },
{ 0 }
};
#endif
void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
__u64 valid, const struct lu_fid *fid,
- struct obd_capa *oc, int ea_size, int flags);
+ struct obd_capa *oc, int ea_size,
+ __u32 suppgid, int flags);
void mdc_pack_capa(struct ptlrpc_request *req, int offset, struct obd_capa *oc);
void mdc_pack_rep_body(struct ptlrpc_request *);
void mdc_is_subdir_pack(struct ptlrpc_request *req, int offset,
#endif
#endif
-static void mdc_pack_body(struct mdt_body *b)
+static void mdc_pack_body(struct mdt_body *b, __u32 suppgid)
{
LASSERT (b != NULL);
+ b->suppgid = suppgid;
+ b->uid = current->uid;
+ b->gid = current->gid;
b->fsuid = current->fsuid;
b->fsgid = current->fsgid;
b->capability = current->cap_effective;
void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
__u64 valid, const struct lu_fid *fid,
- struct obd_capa *oc, int ea_size, int flags)
+ struct obd_capa *oc, int ea_size, __u32 suppgid,
+ int flags)
{
struct mdt_body *b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
b->valid = valid;
b->eadatasize = ea_size;
b->flags = flags;
- mdc_pack_body(b);
+ mdc_pack_body(b, suppgid);
if (fid) {
b->fid1 = *fid;
mdc_pack_capa(req, offset + 1, oc);
b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
b->fid1 = *fid;
b->size = pgoff; /* !! */
- b->suppgid = -1;
b->nlink = size; /* !! */
- mdc_pack_body(b);
+ mdc_pack_body(b, -1);
mdc_pack_capa(req, offset + 1, oc);
}
req->rq_send_state = level;
ptlrpc_req_set_repsize(req, 3, size);
- mdc_pack_req_body(req, REQ_REC_OFF, 0, NULL, NULL, 0, 0);
+ mdc_pack_req_body(req, REQ_REC_OFF, 0, NULL, NULL, 0, -1, 0);
lustre_msg_add_flags(req->rq_reqmsg, msg_flags);
rc = ptlrpc_queue_wait(req);
if (!req)
GOTO(out, rc = -ENOMEM);
- mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size,
+ mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size, -1,
MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
if (valid & OBD_MD_FLRMTPERM)
int mdc_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
struct obd_capa *oc, const char *filename, int namelen,
- obd_valid valid, int ea_size,
+ obd_valid valid, int ea_size, __u32 suppgid,
struct ptlrpc_request **request)
{
struct ptlrpc_request *req;
if (!req)
GOTO(out, rc = -ENOMEM);
- mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size,
+ mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size, suppgid,
MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
if (filename) {
struct obd_capa *oc,
int opcode, obd_valid valid, const char *xattr_name,
const char *input, int input_size, int output_size,
- int flags, struct ptlrpc_request **request)
+ int flags, __u32 suppgid, struct ptlrpc_request **request)
{
struct ptlrpc_request *req;
int size[5] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
int bufcnt = 3, offset = REQ_REC_OFF + 2;
- int rc, xattr_namelen = 0, remote_acl = 0;
+ int rc, xattr_namelen = 0;
void *tmp;
ENTRY;
GOTO(out, rc = -ENOMEM);
/* request data */
- mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, output_size, flags);
+ mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, output_size,
+ suppgid, flags);
if (xattr_name) {
tmp = lustre_msg_buf(req->rq_reqmsg, offset++, xattr_namelen);
memcpy(tmp, xattr_name, xattr_namelen);
- if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
- remote_acl = 1;
}
if (input_size) {
tmp = lustre_msg_buf(req->rq_reqmsg, offset++, input_size);
ptlrpc_req_set_repsize(req, bufcnt, size);
/* make rpc */
- /* NB: set remote acl doesn't need hold rpc lock, because it just
- * send command to MDS, and when it's executed on mountpoint on MDS,
- * another mdc_xattr_common() will be invoked there. */
- if (opcode == MDS_SETXATTR && !remote_acl)
+ if (opcode == MDS_SETXATTR)
mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
rc = ptlrpc_queue_wait(req);
- if (opcode == MDS_SETXATTR && !remote_acl)
+ if (opcode == MDS_SETXATTR)
mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
if (rc != 0)
int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid,
struct obd_capa *oc, obd_valid valid, const char *xattr_name,
const char *input, int input_size, int output_size, int flags,
- struct ptlrpc_request **request)
+ __u32 suppgid, struct ptlrpc_request **request)
{
return mdc_xattr_common(exp, fid, oc, MDS_SETXATTR, valid, xattr_name,
- input, input_size, output_size, flags, request);
+ input, input_size, output_size, flags, suppgid,
+ request);
}
int mdc_getxattr(struct obd_export *exp, const struct lu_fid *fid,
struct ptlrpc_request **request)
{
return mdc_xattr_common(exp, fid, oc, MDS_GETXATTR, valid, xattr_name,
- input, input_size, output_size, flags, request);
+ input, input_size, output_size, flags, -1,
+ request);
}
#ifdef CONFIG_FS_POSIX_ACL
if (!req)
RETURN(rc = -ENOMEM);
- mdc_pack_req_body(req, REQ_REC_OFF, 0, fid, oc, 0, 0);
+ mdc_pack_req_body(req, REQ_REC_OFF, 0, fid, oc, 0, -1, 0);
ptlrpc_req_set_repsize(req, 2, size);
GOTO(err_close_lock, rc);
lprocfs_mdc_init_vars(&lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
+ sptlrpc_lprocfs_cliobd_attach(obd);
ptlrpc_lprocfs_register_obd(obd);
rc = obd_llog_init(obd, NULL, obd, 0, NULL, NULL);
int rc = 0;
lprocfs_mdc_init_vars(&lvars);
-
- rc = class_process_proc_param(PARAM_MDC, lvars.obd_vars, lcfg, obd);
+
+ switch (lcfg->lcfg_command) {
+ case LCFG_SPTLRPC_CONF:
+ rc = sptlrpc_cliobd_process_config(obd, lcfg);
+ break;
+ default:
+ rc = class_process_proc_param(PARAM_MDC, lvars.obd_vars,
+ lcfg, obd);
+ break;
+ }
return(rc);
}
/* get remote permission for current user on fid */
int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
- struct obd_capa *oc, struct ptlrpc_request **request)
+ struct obd_capa *oc, __u32 suppgid,
+ struct ptlrpc_request **request)
{
struct ptlrpc_request *req;
struct mdt_body *body;
if (!req)
RETURN(-ENOMEM);
- mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLRMTPERM, fid, oc, 0, 0);
+ mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLRMTPERM, fid, oc, 0,
+ suppgid, 0);
size[REPLY_REC_OFF + 1] = sizeof(*perm);
ptlrpc_req_set_repsize(req, 5, size);
RETURN(-ENOMEM);
mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLOSSCAPA,
- &oc->c_capa.lc_fid, oc, 0, 0);
+ &oc->c_capa.lc_fid, oc, 0, -1, 0);
ptlrpc_req_set_repsize(req, 5, size);
req->rq_async_args.pointer_arg[0] = oc;
#include <asm/semaphore.h>
#include <linux/lustre_acl.h>
+#include <lustre_eacl.h>
#include <obd.h>
#include <md_object.h>
#include <dt_object.h>
return 0;
}
-int mdd_in_group_p(struct md_ucred *uc, gid_t grp);
int mdd_acl_def_get(const struct lu_env *env, struct mdd_object *mdd_obj,
struct md_attr *ma);
int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
(tmp_la->la_mode & ~S_IALLUGO);
/* Also check the setgid bit! */
- if (!mdd_in_group_p(uc, (la->la_valid & LA_GID) ? la->la_gid :
+ if (!lustre_in_group_p(uc, (la->la_valid & LA_GID) ? la->la_gid :
tmp_la->la_gid) && !mdd_capable(uc, CAP_FSETID))
la->la_mode &= ~S_ISGID;
} else {
la->la_gid = tmp_la->la_gid;
if (((uc->mu_fsuid != tmp_la->la_uid) ||
((la->la_gid != tmp_la->la_gid) &&
- !mdd_in_group_p(uc, la->la_gid))) &&
+ !lustre_in_group_p(uc, la->la_gid))) &&
!mdd_capable(uc, CAP_CHOWN))
RETURN(-EPERM);
#include <lustre_mds.h>
#include <lustre/lustre_idl.h>
-#ifdef CONFIG_FS_POSIX_ACL
-# include <linux/posix_acl_xattr.h>
-# include <linux/posix_acl.h>
-#endif
-
#include "mdd_internal.h"
-#define mdd_get_group_info(group_info) do { \
- atomic_inc(&(group_info)->usage); \
-} while (0)
-
-#define mdd_put_group_info(group_info) do { \
- if (atomic_dec_and_test(&(group_info)->usage)) \
- groups_free(group_info); \
-} while (0)
-
-#define MDD_NGROUPS_PER_BLOCK ((int)(CFS_PAGE_SIZE / sizeof(gid_t)))
-
-#define MDD_GROUP_AT(gi, i) \
- ((gi)->blocks[(i) / MDD_NGROUPS_PER_BLOCK][(i) % MDD_NGROUPS_PER_BLOCK])
-
-/*
- * groups_search() is copied from linux kernel!
- * A simple bsearch.
- */
-static int mdd_groups_search(struct group_info *group_info, gid_t grp)
-{
- int left, right;
-
- if (!group_info)
- return 0;
-
- left = 0;
- right = group_info->ngroups;
- while (left < right) {
- int mid = (left + right) / 2;
- int cmp = grp - MDD_GROUP_AT(group_info, mid);
-
- if (cmp > 0)
- left = mid + 1;
- else if (cmp < 0)
- right = mid;
- else
- return 1;
- }
- return 0;
-}
-
-int mdd_in_group_p(struct md_ucred *uc, gid_t grp)
-{
- int rc = 1;
-
- if (grp != uc->mu_fsgid) {
- struct group_info *group_info = NULL;
-
- if (uc->mu_ginfo || !uc->mu_identity ||
- uc->mu_valid == UCRED_OLD)
- if (grp == uc->mu_suppgids[0] ||
- grp == uc->mu_suppgids[1])
- return 1;
-
- if (uc->mu_ginfo)
- group_info = uc->mu_ginfo;
- else if (uc->mu_identity)
- group_info = uc->mu_identity->mi_ginfo;
-
- if (!group_info)
- return 0;
-
- mdd_get_group_info(group_info);
- rc = mdd_groups_search(group_info, grp);
- mdd_put_group_info(group_info);
- }
- return rc;
-}
-
#ifdef CONFIG_FS_POSIX_ACL
-static inline void mdd_acl_le_to_cpu(posix_acl_xattr_entry *p)
-{
- p->e_tag = le16_to_cpu(p->e_tag);
- p->e_perm = le16_to_cpu(p->e_perm);
- p->e_id = le32_to_cpu(p->e_id);
-}
-
-static inline void mdd_acl_cpu_to_le(posix_acl_xattr_entry *p)
-{
- p->e_tag = cpu_to_le16(p->e_tag);
- p->e_perm = cpu_to_le16(p->e_perm);
- p->e_id = cpu_to_le32(p->e_id);
-}
-
-/*
- * Check permission based on POSIX ACL.
- */
-static int mdd_posix_acl_permission(struct md_ucred *uc, struct lu_attr *la,
- int want, posix_acl_xattr_entry *entry,
- int count)
-{
- posix_acl_xattr_entry *pa, *pe, *mask_obj;
- int found = 0;
- ENTRY;
-
- if (count <= 0)
- RETURN(-EACCES);
-
- for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
- mdd_acl_le_to_cpu(pa);
- switch(pa->e_tag) {
- case ACL_USER_OBJ:
- /* (May have been checked already) */
- if (la->la_uid == uc->mu_fsuid)
- goto check_perm;
- break;
- case ACL_USER:
- if (pa->e_id == uc->mu_fsuid)
- goto mask;
- break;
- case ACL_GROUP_OBJ:
- if (mdd_in_group_p(uc, la->la_gid)) {
- found = 1;
- if ((pa->e_perm & want) == want)
- goto mask;
- }
- break;
- case ACL_GROUP:
- if (mdd_in_group_p(uc, pa->e_id)) {
- found = 1;
- if ((pa->e_perm & want) == want)
- goto mask;
- }
- break;
- case ACL_MASK:
- break;
- case ACL_OTHER:
- if (found)
- RETURN(-EACCES);
- else
- goto check_perm;
- default:
- RETURN(-EIO);
- }
- }
- RETURN(-EIO);
-
-mask:
- for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
- mdd_acl_le_to_cpu(mask_obj);
- if (mask_obj->e_tag == ACL_MASK) {
- if ((pa->e_perm & mask_obj->e_perm & want) == want)
- RETURN(0);
-
- RETURN(-EACCES);
- }
- }
-
-check_perm:
- if ((pa->e_perm & want) == want)
- RETURN(0);
-
- RETURN(-EACCES);
-}
/*
* Get default acl EA only.
}
/*
- * Modify the ACL for the chmod.
- */
-static int mdd_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
- __u32 mode, int count)
-{
- posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
-
- for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
- mdd_acl_le_to_cpu(pa);
- switch(pa->e_tag) {
- case ACL_USER_OBJ:
- pa->e_perm = (mode & S_IRWXU) >> 6;
- break;
-
- case ACL_USER:
- case ACL_GROUP:
- break;
-
- case ACL_GROUP_OBJ:
- group_obj = pa;
- break;
-
- case ACL_MASK:
- mask_obj = pa;
- break;
-
- case ACL_OTHER:
- pa->e_perm = (mode & S_IRWXO);
- break;
-
- default:
- return -EIO;
- }
- mdd_acl_cpu_to_le(pa);
- }
-
- if (mask_obj) {
- mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
- } else {
- if (!group_obj)
- return -EIO;
- group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
- }
-
- return 0;
-}
-
-/*
* Hold write_lock for o.
*/
int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
if (entry_count <= 0)
RETURN(0);
- rc = mdd_posix_acl_chmod_masq(entry, mode, entry_count);
+ rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
if (rc)
RETURN(rc);
}
/*
- * Modify acl when creating a new obj.
- */
-static int mdd_posix_acl_create_masq(posix_acl_xattr_entry *entry,
- __u32 *mode_p, int count)
-{
- posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
- __u32 mode = *mode_p;
- int not_equiv = 0;
-
- for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
- mdd_acl_le_to_cpu(pa);
- switch(pa->e_tag) {
- case ACL_USER_OBJ:
- pa->e_perm &= (mode >> 6) | ~S_IRWXO;
- mode &= (pa->e_perm << 6) | ~S_IRWXU;
- break;
-
- case ACL_USER:
- case ACL_GROUP:
- not_equiv = 1;
- break;
-
- case ACL_GROUP_OBJ:
- group_obj = pa;
- break;
-
- case ACL_OTHER:
- pa->e_perm &= mode | ~S_IRWXO;
- mode &= pa->e_perm | ~S_IRWXO;
- break;
-
- case ACL_MASK:
- mask_obj = pa;
- not_equiv = 1;
- break;
-
- default:
- return -EIO;
- }
- mdd_acl_cpu_to_le(pa);
- }
-
- if (mask_obj) {
- mask_obj->e_perm = le16_to_cpu(mask_obj->e_perm) &
- ((mode >> 3) | ~S_IRWXO);
- mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
- mask_obj->e_perm = cpu_to_le16(mask_obj->e_perm);
- } else {
- if (!group_obj)
- return -EIO;
- group_obj->e_perm = le16_to_cpu(group_obj->e_perm) &
- ((mode >> 3) | ~S_IRWXO);
- mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
- group_obj->e_perm = cpu_to_le16(group_obj->e_perm);
- }
-
- *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
- return not_equiv;
-}
-
-/*
* Hold write_lock for obj.
*/
int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
RETURN(rc);
}
- rc = mdd_posix_acl_create_masq(entry, mode, entry_count);
+ rc = lustre_posix_acl_create_masq(entry, mode, entry_count);
if (rc <= 0)
RETURN(rc);
entry_count = (buf->lb_len - sizeof(head->a_version)) /
sizeof(posix_acl_xattr_entry);
- rc = mdd_posix_acl_permission(uc, la, mask, entry, entry_count);
+ rc = lustre_posix_acl_permission(uc, la, mask, entry, entry_count);
RETURN(rc);
#else
ENTRY;
(rc != -ENODATA))
RETURN(rc);
}
- if (mdd_in_group_p(uc, la->la_gid))
+ if (lustre_in_group_p(uc, la->la_gid))
mode >>= 3;
}
struct md_attr *ma, int mask)
{
struct mdd_object *mdd_pobj, *mdd_cobj;
+ struct md_ucred *uc = NULL;
struct lu_attr *la = NULL;
int check_create, check_link;
int check_unlink;
int check_rename_src, check_rename_tar;
int check_vtx_part, check_vtx_full;
+ int check_rgetfacl;
int rc = 0;
ENTRY;
check_rename_tar = mask & MAY_RENAME_TAR;
check_vtx_part = mask & MAY_VTX_PART;
check_vtx_full = mask & MAY_VTX_FULL;
+ check_rgetfacl = mask & MAY_RGETFACL;
mask &= ~(MAY_CREATE | MAY_LINK |
MAY_UNLINK |
MAY_RENAME_SRC | MAY_RENAME_TAR |
- MAY_VTX_PART | MAY_VTX_FULL);
+ MAY_VTX_PART | MAY_VTX_FULL |
+ MAY_RGETFACL);
rc = mdd_permission_internal_locked(env, mdd_cobj, NULL, mask);
}
if (!rc && (check_vtx_part || check_vtx_full)) {
- struct md_ucred *uc = md_ucred(env);
-
+ uc = md_ucred(env);
LASSERT(ma);
if (likely(!la)) {
la = &mdd_env_info(env)->mti_la;
}
}
+ if (unlikely(!rc && check_rgetfacl)) {
+ if (likely(!uc))
+ uc = md_ucred(env);
+
+ if (likely(!la)) {
+ la = &mdd_env_info(env)->mti_la;
+ rc = mdd_la_get(env, mdd_cobj, la, BYPASS_CAPA);
+ if (rc)
+ RETURN(rc);
+ }
+
+ if (la->la_uid != uc->mu_fsuid && !mdd_capable(uc, CAP_FOWNER))
+ rc = -EPERM;
+ }
+
RETURN(rc);
}
return 0;
}
-static int mds_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int mds_reconnect(const struct lu_env *env,
+ struct obd_export *exp, struct obd_device *obd,
struct obd_uuid *cluuid,
struct obd_connect_data *data)
{
LASSERT(exp);
med = &exp->exp_mds_data;
+ exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
+
rc = mds_connect_internal(exp, data);
if (rc)
GOTO(out, rc);
MODULES := mdt
mdt-objs := mdt_handler.o mdt_lib.o mdt_reint.o mdt_xattr.o mdt_recovery.o
-mdt-objs += mdt_open.o mdt_idmap.o mdt_identity.o mdt_rmtacl.o mdt_capa.o mdt_lproc.o
+mdt-objs += mdt_open.o mdt_idmap.o mdt_identity.o mdt_capa.o mdt_lproc.o
@INCLUDE_RULES@
if (reqbody == NULL || repbody == NULL)
RETURN(err_serious(-EFAULT));
- rc = mdt_check_ucred(info);
- if (rc)
- RETURN(err_serious(rc));
-
/*
* prepare @rdpg before calling lower layers and transfer itself. Here
* reqbody->size contains offset of where to start to read and
mdt_fs_cleanup(env, m);
- upcall_cache_cleanup(m->mdt_rmtacl_cache);
- m->mdt_rmtacl_cache = NULL;
-
upcall_cache_cleanup(m->mdt_identity_cache);
m->mdt_identity_cache = NULL;
ptlrpc_lprocfs_unregister_obd(d->ld_obd);
lprocfs_obd_cleanup(d->ld_obd);
- if (m->mdt_rootsquash_info) {
- OBD_FREE_PTR(m->mdt_rootsquash_info);
- m->mdt_rootsquash_info = NULL;
- }
+ sptlrpc_rule_set_free(&m->mdt_sptlrpc_rset);
next->md_ops->mdo_init_capa_ctxt(env, next, 0, 0, 0, NULL);
del_timer(&m->mdt_ck_timer);
struct lustre_mount_info *lmi;
struct lustre_sb_info *lsi;
struct lu_site *s;
+ const char *identity_upcall = "NONE";
int rc;
ENTRY;
server_put_mount_2(dev, lmi->lmi_mnt);
}
+ m->mdt_sptlrpc_lock = RW_LOCK_UNLOCKED;
+ sptlrpc_rule_set_init(&m->mdt_sptlrpc_rset);
+
spin_lock_init(&m->mdt_ioepoch_lock);
m->mdt_opts.mo_compat_resname = 0;
m->mdt_capa_timeout = CAPA_TIMEOUT;
/* set obd_namespace for compatibility with old code */
obd->obd_namespace = m->mdt_namespace;
- m->mdt_identity_cache = upcall_cache_init(obd->obd_name,
- "NONE",
+ /* XXX: to support suppgid for ACL, we enable identity_upcall
+ * by default, otherwise, maybe got unexpected -EACCESS. */
+ if (m->mdt_opts.mo_acl)
+ identity_upcall = MDT_IDENTITY_UPCALL_PATH;
+
+ m->mdt_identity_cache = upcall_cache_init(obd->obd_name, identity_upcall,
&mdt_identity_upcall_cache_ops);
if (IS_ERR(m->mdt_identity_cache)) {
rc = PTR_ERR(m->mdt_identity_cache);
GOTO(err_free_ns, rc);
}
- m->mdt_rmtacl_cache = upcall_cache_init(obd->obd_name,
- MDT_RMTACL_UPCALL_PATH,
- &mdt_rmtacl_upcall_cache_ops);
- if (IS_ERR(m->mdt_rmtacl_cache)) {
- rc = PTR_ERR(m->mdt_rmtacl_cache);
- m->mdt_rmtacl_cache = NULL;
- GOTO(err_free_ns, rc);
- }
-
m->mdt_ck_timer.function = mdt_ck_timer_callback;
m->mdt_ck_timer.data = (unsigned long)m;
init_timer(&m->mdt_ck_timer);
del_timer(&m->mdt_ck_timer);
mdt_ck_thread_stop(m);
err_free_ns:
- upcall_cache_cleanup(m->mdt_rmtacl_cache);
- m->mdt_rmtacl_cache = NULL;
upcall_cache_cleanup(m->mdt_identity_cache);
m->mdt_identity_cache = NULL;
ldlm_namespace_free(m->mdt_namespace, 0);
ENTRY;
switch (cfg->lcfg_command) {
+ case LCFG_SPTLRPC_CONF: {
+ struct sptlrpc_conf_log *log;
+ struct sptlrpc_rule_set tmp_rset;
+
+ log = sptlrpc_conf_log_extract(cfg);
+ if (IS_ERR(log)) {
+ rc = PTR_ERR(log);
+ break;
+ }
+
+ sptlrpc_rule_set_init(&tmp_rset);
+
+ rc = sptlrpc_rule_set_from_log(&tmp_rset, log);
+ if (rc) {
+ CERROR("mdt %p: failed get sptlrpc rules: %d\n", m, rc);
+ break;
+ }
+
+ write_lock(&m->mdt_sptlrpc_lock);
+ sptlrpc_rule_set_free(&m->mdt_sptlrpc_rset);
+ m->mdt_sptlrpc_rset = tmp_rset;
+ write_unlock(&m->mdt_sptlrpc_lock);
+
+ sptlrpc_target_update_exp_flavor(
+ md2lu_dev(&m->mdt_md_dev)->ld_obd, &tmp_rset);
+
+ break;
+ }
case LCFG_PARAM: {
struct lprocfs_static_vars lvars;
struct obd_device *obd = d->ld_obd;
struct obd_uuid *cluuid,
struct obd_connect_data *data)
{
+ struct mdt_thread_info *info;
struct mdt_client_data *mcd;
struct obd_export *exp;
struct mdt_device *mdt;
+ struct ptlrpc_request *req;
int rc;
ENTRY;
if (!conn || !obd || !cluuid)
RETURN(-EINVAL);
+ info = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
+ req = info->mti_pill.rc_req;
mdt = mdt_dev(obd->obd_lu_dev);
rc = class_connect(conn, obd, cluuid);
exp = class_conn2export(conn);
LASSERT(exp != NULL);
+ CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
+
+ spin_lock(&exp->exp_lock);
+ exp->exp_sp_peer = req->rq_sp_from;
+
+ read_lock(&mdt->mdt_sptlrpc_lock);
+ sptlrpc_rule_set_choose(&mdt->mdt_sptlrpc_rset, exp->exp_sp_peer,
+ req->rq_peer.nid, &exp->exp_flvr);
+ read_unlock(&mdt->mdt_sptlrpc_lock);
+
+ if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+ req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+ libcfs_nid2str(req->rq_peer.nid));
+ exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+ spin_unlock(&exp->exp_lock);
+ RETURN(-EACCES);
+ }
+ spin_unlock(&exp->exp_lock);
+
rc = mdt_connect_internal(exp, mdt, data);
if (rc == 0) {
OBD_ALLOC_PTR(mcd);
RETURN(rc);
}
-static int mdt_obd_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int mdt_obd_reconnect(const struct lu_env *env,
+ struct obd_export *exp, struct obd_device *obd,
struct obd_uuid *cluuid,
struct obd_connect_data *data)
{
- int rc;
+ struct mdt_thread_info *info;
+ struct mdt_device *mdt;
+ struct ptlrpc_request *req;
+ int rc;
ENTRY;
if (exp == NULL || obd == NULL || cluuid == NULL)
RETURN(-EINVAL);
+ info = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
+ req = info->mti_pill.rc_req;
+ mdt = mdt_dev(obd->obd_lu_dev);
+
+ CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
+
+ spin_lock(&exp->exp_lock);
+ if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
+ exp->exp_sp_peer = req->rq_sp_from;
+
+ read_lock(&mdt->mdt_sptlrpc_lock);
+ sptlrpc_rule_set_choose(&mdt->mdt_sptlrpc_rset,
+ exp->exp_sp_peer,
+ req->rq_peer.nid, &exp->exp_flvr);
+ read_unlock(&mdt->mdt_sptlrpc_lock);
+
+ if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+ req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+ libcfs_nid2str(req->rq_peer.nid));
+ exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+ spin_unlock(&exp->exp_lock);
+ RETURN(-EACCES);
+ }
+ }
+ spin_unlock(&exp->exp_lock);
+
rc = mdt_connect_internal(exp, mdt_dev(obd->obd_lu_dev), data);
RETURN(rc);
INIT_LIST_HEAD(&med->med_open_head);
spin_lock_init(&med->med_open_lock);
+ sema_init(&med->med_idmap_sem, 1);
+ med->med_idmap = NULL;
spin_lock(&exp->exp_lock);
exp->exp_connecting = 1;
spin_unlock(&exp->exp_lock);
.mos_hs = mdt_obd_ops
},
{
+ .mos_opc_start = SEC_CTX_INIT,
+ .mos_opc_end = SEC_LAST_OPC,
+ .mos_hs = mdt_sec_ctx_ops
+ },
+ {
.mos_hs = NULL
}
};
static void mdt_identity_entry_free(struct upcall_cache *cache,
struct upcall_cache_entry *entry)
{
- struct mdt_identity *identity = &entry->u.identity;
+ struct md_identity *identity = &entry->u.identity;
- if (identity->mi_ginfo)
+ if (identity->mi_ginfo) {
groups_free(identity->mi_ginfo);
+ identity->mi_ginfo = NULL;
+ }
if (identity->mi_nperms) {
LASSERT(identity->mi_perms);
OBD_FREE(identity->mi_perms,
- identity->mi_nperms * sizeof(struct mdt_setxid_perm));
+ identity->mi_nperms * sizeof(struct md_perm));
+ identity->mi_nperms = 0;
}
}
struct upcall_cache_entry *entry,
void *args)
{
- struct mdt_identity *identity = &entry->u.identity;
+ struct md_identity *identity = &entry->u.identity;
struct identity_downcall_data *data = args;
struct group_info *ginfo;
- struct mdt_setxid_perm *perms = NULL;
+ struct md_perm *perms = NULL;
int size, i;
ENTRY;
RETURN(-ENOMEM);
}
- groups_from_list(ginfo, data->idd_groups);
- groups_sort(ginfo);
- identity->mi_ginfo = ginfo;
+ lustre_groups_from_list(ginfo, data->idd_groups);
+ lustre_groups_sort(ginfo);
if (data->idd_nperms) {
size = data->idd_nperms * sizeof(*perms);
if (!perms) {
CERROR("failed to alloc %d permissions\n",
data->idd_nperms);
- put_group_info(ginfo);
+ groups_free(ginfo);
RETURN(-ENOMEM);
}
+
for (i = 0; i < data->idd_nperms; i++) {
perms[i].mp_nid = data->idd_perms[i].pdd_nid;
perms[i].mp_perm = data->idd_perms[i].pdd_perm;
RETURN(0);
}
-struct mdt_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
+struct md_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
{
struct upcall_cache_entry *entry;
return &entry->u.identity;
}
-void mdt_identity_put(struct upcall_cache *cache, struct mdt_identity *identity)
+void mdt_identity_put(struct upcall_cache *cache, struct md_identity *identity)
{
if (!cache)
return;
* If there is LNET_NID_ANY in perm[i].mp_nid,
* it must be perm[0].mp_nid, and act as default perm.
*/
-__u32 mdt_identity_get_setxid_perm(struct mdt_identity *identity,
+__u32 mdt_identity_get_perm(struct md_identity *identity,
__u32 is_rmtclient, lnet_nid_t nid)
{
- struct mdt_setxid_perm *perm = identity->mi_perms;
+ struct md_perm *perm;
int i;
+ if (!identity) {
+ LASSERT(is_rmtclient == 0);
+ return CFS_SETGRP_PERM;
+ }
+
+ perm = identity->mi_perms;
/* check exactly matched nid first */
for (i = identity->mi_nperms - 1; i > 0; i--) {
if (perm[i].mp_nid != nid)
return perm[0].mp_perm;
/* return default last */
- return is_rmtclient ? 0 : LUSTRE_SETGRP_PERM;
+ return is_rmtclient ? 0 : CFS_SETGRP_PERM;
}
int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
#endif
#define DEBUG_SUBSYSTEM S_MDS
-#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
-#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include "mdt_internal.h"
-enum {
- MDT_IDMAP_NOTFOUND = -1,
-};
-
-struct mdt_idmap_entry {
- struct list_head mie_rmt_hash; /* hashed as mie_rmt_id; */
- struct list_head mie_lcl_hash; /* hashed as mie_lcl_id; */
- int mie_refcount;
- uid_t mie_rmt_id; /* remote uid/gid */
- uid_t mie_lcl_id; /* local uid/gid */
-};
-
-/* uid/gid mapping */
-static struct mdt_idmap_table *mdt_idmap_alloc(void)
-{
- struct mdt_idmap_table *tbl;
- int i, j;
-
- OBD_ALLOC_PTR(tbl);
- if (!tbl)
- return NULL;
-
- spin_lock_init(&tbl->mit_lock);
- for (i = 0; i < ARRAY_SIZE(tbl->mit_idmaps); i++)
- for (j = 0; j < ARRAY_SIZE(tbl->mit_idmaps[i]); j++)
- INIT_LIST_HEAD(&tbl->mit_idmaps[i][j]);
-
- return tbl;
-}
-
-static struct mdt_idmap_entry *idmap_entry_alloc(__u32 mie_rmt_id,
- __u32 mie_lcl_id)
-{
- struct mdt_idmap_entry *e;
-
- OBD_ALLOC_PTR(e);
- if (!e)
- return NULL;
-
- INIT_LIST_HEAD(&e->mie_rmt_hash);
- INIT_LIST_HEAD(&e->mie_lcl_hash);
- e->mie_refcount = 1;
- e->mie_rmt_id = mie_rmt_id;
- e->mie_lcl_id = mie_lcl_id;
-
- return e;
-}
-
-static void idmap_entry_free(struct mdt_idmap_entry *e)
-{
- if (!list_empty(&e->mie_rmt_hash))
- list_del(&e->mie_rmt_hash);
- if (!list_empty(&e->mie_lcl_hash))
- list_del(&e->mie_lcl_hash);
- OBD_FREE_PTR(e);
-}
-
int mdt_init_idmap(struct mdt_thread_info *info)
{
struct ptlrpc_request *req = mdt_info_req(info);
if (!req->rq_auth_gss || req->rq_auth_usr_mdt) {
med->med_rmtclient = 0;
reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
- //reply->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
RETURN(0);
}
}
if (med->med_rmtclient) {
- med->med_nllu = data->ocd_nllu;
- med->med_nllg = data->ocd_nllg;
+ down(&med->med_idmap_sem);
if (!med->med_idmap)
- med->med_idmap = mdt_idmap_alloc();
- if (!med->med_idmap) {
- CERROR("client %s -> target %s failed to alloc idmap!\n"
- , client, obd->obd_name);
+ med->med_idmap = lustre_idmap_init();
+ up(&med->med_idmap_sem);
+
+ if (IS_ERR(med->med_idmap)) {
+ long err = PTR_ERR(med->med_idmap);
+
+ med->med_idmap = NULL;
+ CERROR("client %s -> target %s "
+ "failed to init idmap [%ld]!\n",
+ client, obd->obd_name, err);
+ RETURN(err);
+ } else if (!med->med_idmap) {
+ CERROR("client %s -> target %s "
+ "failed to init(2) idmap!\n",
+ client, obd->obd_name);
RETURN(-ENOMEM);
}
reply->ocd_connect_flags &= ~OBD_CONNECT_LCL_CLIENT;
- //reply->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT;
CDEBUG(D_SEC, "client %s -> target %s is remote.\n",
client, obd->obd_name);
- /* NB, MDT_CONNECT establish root idmap too! */
+ /* NB, MDS_CONNECT establish root idmap too! */
rc = mdt_handle_idmap(info);
} else {
if (req->rq_auth_uid == INVALID_UID) {
RETURN(-EACCES);
}
reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
- //reply->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
}
RETURN(rc);
}
-static void idmap_clear_mie_rmt_hash(struct list_head *list)
-{
- struct mdt_idmap_entry *e;
- int i;
-
- for (i = 0; i < MDT_IDMAP_HASHSIZE; i++) {
- while (!list_empty(&list[i])) {
- e = list_entry(list[i].next, struct mdt_idmap_entry,
- mie_rmt_hash);
- idmap_entry_free(e);
- }
- }
-}
-
void mdt_cleanup_idmap(struct mdt_export_data *med)
{
- struct mdt_idmap_table *tbl = med->med_idmap;
- int i;
-
LASSERT(med->med_rmtclient);
- LASSERT(tbl);
-
- spin_lock(&tbl->mit_lock);
- idmap_clear_mie_rmt_hash(tbl->mit_idmaps[RMT_UIDMAP_IDX]);
- idmap_clear_mie_rmt_hash(tbl->mit_idmaps[RMT_GIDMAP_IDX]);
-
- /* paranoid checking */
- for (i = 0; i < MDT_IDMAP_HASHSIZE; i++) {
- LASSERT(list_empty(&tbl->mit_idmaps[LCL_UIDMAP_IDX][i]));
- LASSERT(list_empty(&tbl->mit_idmaps[LCL_GIDMAP_IDX][i]));
- }
- spin_unlock(&tbl->mit_lock);
- OBD_FREE_PTR(tbl);
+ down(&med->med_idmap_sem);
+ if (med->med_idmap != NULL) {
+ lustre_idmap_fini(med->med_idmap);
med->med_idmap = NULL;
+ }
+ up(&med->med_idmap_sem);
}
static inline void mdt_revoke_export_locks(struct obd_export *exp)
ldlm_revoke_export_locks(exp);
}
-static
-struct mdt_idmap_entry *idmap_lookup_entry(struct list_head *mie_rmt_hash,
- uid_t mie_rmt_id, uid_t mie_lcl_id)
-{
- struct list_head *rmt_head =
- &mie_rmt_hash[MDT_IDMAP_HASHFUNC(mie_rmt_id)];
- struct mdt_idmap_entry *e;
-
- list_for_each_entry(e, rmt_head, mie_rmt_hash) {
- if ((e->mie_rmt_id == mie_rmt_id) &&
- (e->mie_lcl_id == mie_lcl_id))
- return e;
- }
- return NULL;
-}
-
-/*
- * return value
- * NULL: not found entry
- * ERR_PTR(-EACCES): found multi->single mapped entry
- * others: found normal entry
- */
-static
-struct mdt_idmap_entry *idmap_search_entry(struct list_head *mie_rmt_hash,
- uid_t mie_rmt_id,
- struct list_head *mie_lcl_hash,
- uid_t mie_lcl_id,
- const char *warn_msg)
-{
- struct list_head *rmt_head =
- &mie_rmt_hash[MDT_IDMAP_HASHFUNC(mie_rmt_id)];
- struct list_head *lcl_head =
- &mie_lcl_hash[MDT_IDMAP_HASHFUNC(mie_lcl_id)];
- struct mdt_idmap_entry *e;
-
- list_for_each_entry(e, rmt_head, mie_rmt_hash) {
- if (e->mie_rmt_id == mie_rmt_id) {
- if (e->mie_lcl_id == mie_lcl_id) {
- e->mie_refcount++;
- return e;
- } else {
- CERROR("%s: rmt id %u already be mapped to %u"
- " (new %u)\n", warn_msg, e->mie_rmt_id,
- e->mie_lcl_id, mie_lcl_id);
- return ERR_PTR(-EACCES);
- }
- }
- }
-
- list_for_each_entry(e, lcl_head, mie_lcl_hash) {
- if (e->mie_lcl_id == mie_lcl_id) {
- if (e->mie_rmt_id == mie_rmt_id) {
- e->mie_refcount++;
- return e;
- } else {
- CERROR("%s: lcl id %u already be mapped from %u"
- " (new %u)\n", warn_msg, e->mie_lcl_id,
- e->mie_rmt_id, mie_rmt_id);
- return ERR_PTR(-EACCES);
- }
- }
- }
-
- return NULL;
-}
-
-static
-struct mdt_idmap_entry *idmap_insert_entry(struct list_head *mie_rmt_hash,
- struct list_head *mie_lcl_hash,
- struct mdt_idmap_entry *new,
- const char *warn_msg)
-{
- struct list_head *rmt_head =
- &mie_rmt_hash[MDT_IDMAP_HASHFUNC(new->mie_rmt_id)];
- struct list_head *lcl_head =
- &mie_lcl_hash[MDT_IDMAP_HASHFUNC(new->mie_lcl_id)];
- struct mdt_idmap_entry *e;
-
- e = idmap_search_entry(mie_rmt_hash, new->mie_rmt_id,
- mie_lcl_hash, new->mie_lcl_id,
- warn_msg);
- if (e == NULL) {
- list_add_tail(&new->mie_rmt_hash, rmt_head);
- list_add_tail(&new->mie_lcl_hash, lcl_head);
- }
- return e;
-}
-
-static int idmap_remove_entry(struct list_head *mie_rmt_hash,
- struct list_head *mie_lcl_hash,
- __u32 mie_rmt_id, __u32 mie_lcl_id)
-{
- struct mdt_idmap_entry *e;
- int rc = -ENOENT;
-
- e = idmap_lookup_entry(mie_rmt_hash, mie_rmt_id, mie_lcl_id);
- if (e != NULL) {
- e->mie_refcount--;
- if ((rc = e->mie_refcount) <= 0)
- idmap_entry_free(e);
- }
- return rc;
-}
-
-static int mdt_idmap_add(struct mdt_idmap_table *tbl,
- uid_t ruid, uid_t luid,
- gid_t rgid, gid_t lgid)
-{
- struct mdt_idmap_entry *ue0, *ue1, *ge0, *ge1;
- ENTRY;
-
- LASSERT(tbl);
-
- spin_lock(&tbl->mit_lock);
- ue0 = idmap_search_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX], ruid,
- tbl->mit_idmaps[LCL_UIDMAP_IDX], luid,
- "UID mapping");
- spin_unlock(&tbl->mit_lock);
- if (!ue0) {
- ue0 = idmap_entry_alloc(ruid, luid);
- if (!ue0)
- RETURN(-ENOMEM);
-
- spin_lock(&tbl->mit_lock);
- ue1 = idmap_insert_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX],
- tbl->mit_idmaps[LCL_UIDMAP_IDX],
- ue0, "UID mapping");
- if (ue1 != NULL) {
- idmap_entry_free(ue0);
- ue0 = ue1;
- }
- spin_unlock(&tbl->mit_lock);
-
- if (IS_ERR(ue1))
- RETURN(PTR_ERR(ue1));
- } else if (IS_ERR(ue0)) {
- RETURN(PTR_ERR(ue0));
- }
-
- spin_lock(&tbl->mit_lock);
- ge0 = idmap_search_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX], rgid,
- tbl->mit_idmaps[LCL_GIDMAP_IDX], lgid,
- "GID mapping");
- spin_unlock(&tbl->mit_lock);
- if (!ge0) {
- ge0 = idmap_entry_alloc(rgid, lgid);
- spin_lock(&tbl->mit_lock);
- if (!ge0) {
- ue0->mie_refcount--;
- if (ue0->mie_refcount <= 0)
- idmap_entry_free(ue0);
- spin_unlock(&tbl->mit_lock);
- RETURN(-ENOMEM);
- }
-
- ge1 = idmap_insert_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX],
- tbl->mit_idmaps[LCL_GIDMAP_IDX],
- ge0, "GID mapping");
- if (ge1 != NULL) {
- ue0->mie_refcount--;
- if (ue0->mie_refcount <= 0)
- idmap_entry_free(ue0);
- idmap_entry_free(ge0);
- }
- spin_unlock(&tbl->mit_lock);
-
- if (IS_ERR(ge1))
- RETURN(PTR_ERR(ge1));
- } else if (IS_ERR(ge0)) {
- spin_lock(&tbl->mit_lock);
- ue0->mie_refcount--;
- if (ue0->mie_refcount <= 0)
- idmap_entry_free(ue0);
- spin_unlock(&tbl->mit_lock);
- RETURN(PTR_ERR(ge0));
- }
-
- RETURN(0);
-}
-
-static int mdt_idmap_del(struct mdt_idmap_table *tbl,
- uid_t ruid, uid_t luid,
- gid_t rgid, gid_t lgid)
-{
- ENTRY;
-
- if (!tbl)
- RETURN(0);
-
- spin_lock(&tbl->mit_lock);
- idmap_remove_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX],
- tbl->mit_idmaps[LCL_UIDMAP_IDX],
- ruid, luid);
- idmap_remove_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX],
- tbl->mit_idmaps[LCL_GIDMAP_IDX],
- rgid, lgid);
- spin_unlock(&tbl->mit_lock);
-
- RETURN(0);
-}
-
int mdt_handle_idmap(struct mdt_thread_info *info)
{
struct ptlrpc_request *req = mdt_info_req(info);
struct mdt_device *mdt = info->mti_mdt;
struct mdt_export_data *med;
struct ptlrpc_user_desc *pud = req->rq_user_desc;
- struct mdt_identity *identity;
+ struct md_identity *identity;
__u32 opc;
int rc = 0;
-
ENTRY;
if (!req->rq_export)
(opc != SEC_CTX_FINI) && (opc != MDS_CONNECT))
RETURN(0);
- LASSERT(pud);
LASSERT(med->med_idmap);
+ if (unlikely(!pud)) {
+ CERROR("remote client must run with rq_user_desc present\n");
+ RETURN(-EACCES);
+ }
+
if (req->rq_auth_mapped_uid == INVALID_UID) {
CERROR("invalid authorized mapped uid, please check "
"/etc/lustre/idmap.conf!\n");
case SEC_CTX_INIT:
case SEC_CTX_INIT_CONT:
case MDS_CONNECT:
- rc = mdt_idmap_add(med->med_idmap,
+ rc = lustre_idmap_add(med->med_idmap,
pud->pud_uid, identity->mi_uid,
pud->pud_gid, identity->mi_gid);
break;
case SEC_CTX_FINI:
- rc = mdt_idmap_del(med->med_idmap,
+ rc = lustre_idmap_del(med->med_idmap,
pud->pud_uid, identity->mi_uid,
pud->pud_gid, identity->mi_gid);
break;
mdt_revoke_export_locks(req->rq_export);
break;
}
- RETURN(0);
-}
-
-static __u32 idmap_lookup_id(struct list_head *hash, int reverse, __u32 id)
-{
- struct list_head *head = &hash[MDT_IDMAP_HASHFUNC(id)];
- struct mdt_idmap_entry *e;
-
- if (!reverse) {
- list_for_each_entry(e, head, mie_rmt_hash) {
- if (e->mie_rmt_id == id)
- return e->mie_lcl_id;
- }
- } else {
- list_for_each_entry(e, head, mie_lcl_hash) {
- if (e->mie_lcl_id == id)
- return e->mie_rmt_id;
- }
- }
- return MDT_IDMAP_NOTFOUND;
-}
-
-static int mdt_idmap_lookup_uid(struct mdt_idmap_table *tbl, int reverse,
- uid_t uid)
-{
- struct list_head *hash;
-
- if (!tbl)
- return MDT_IDMAP_NOTFOUND;
-
- hash = tbl->mit_idmaps[reverse ? LCL_UIDMAP_IDX : RMT_UIDMAP_IDX];
-
- spin_lock(&tbl->mit_lock);
- uid = idmap_lookup_id(hash, reverse, uid);
- spin_unlock(&tbl->mit_lock);
-
- return uid;
-}
-
-static int mdt_idmap_lookup_gid(struct mdt_idmap_table *tbl, int reverse,
- gid_t gid)
-{
- struct list_head *hash;
-
- if (!tbl)
- return MDT_IDMAP_NOTFOUND;
-
- hash = tbl->mit_idmaps[reverse ? LCL_GIDMAP_IDX : RMT_GIDMAP_IDX];
-
- spin_lock(&tbl->mit_lock);
- gid = idmap_lookup_id(hash, reverse, gid);
- spin_unlock(&tbl->mit_lock);
- return gid;
+ RETURN(0);
}
int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
struct ptlrpc_user_desc *pud)
{
struct mdt_export_data *med = mdt_req2med(req);
- struct mdt_idmap_table *idmap = med->med_idmap;
+ struct lustre_idmap_table *idmap = med->med_idmap;
uid_t uid, fsuid;
gid_t gid, fsgid;
if (!med->med_rmtclient)
return 0;
- uid = mdt_idmap_lookup_uid(idmap, 0, pud->pud_uid);
- if (uid == MDT_IDMAP_NOTFOUND) {
+ uid = lustre_idmap_lookup_uid(NULL, idmap, 0, pud->pud_uid);
+ if (uid == CFS_IDMAP_NOTFOUND) {
CERROR("no mapping for uid %u\n", pud->pud_uid);
return -EACCES;
}
if (pud->pud_uid == pud->pud_fsuid) {
fsuid = uid;
} else {
- fsuid = mdt_idmap_lookup_uid(idmap, 0, pud->pud_fsuid);
- if (fsuid == MDT_IDMAP_NOTFOUND) {
+ fsuid = lustre_idmap_lookup_uid(NULL, idmap, 0, pud->pud_fsuid);
+ if (fsuid == CFS_IDMAP_NOTFOUND) {
CERROR("no mapping for fsuid %u\n", pud->pud_fsuid);
return -EACCES;
}
}
- gid = mdt_idmap_lookup_gid(idmap, 0, pud->pud_gid);
- if (gid == MDT_IDMAP_NOTFOUND) {
+ gid = lustre_idmap_lookup_gid(NULL, idmap, 0, pud->pud_gid);
+ if (gid == CFS_IDMAP_NOTFOUND) {
CERROR("no mapping for gid %u\n", pud->pud_gid);
return -EACCES;
}
if (pud->pud_gid == pud->pud_fsgid) {
fsgid = gid;
} else {
- fsgid = mdt_idmap_lookup_gid(idmap, 0, pud->pud_fsgid);
- if (fsgid == MDT_IDMAP_NOTFOUND) {
+ fsgid = lustre_idmap_lookup_gid(NULL, idmap, 0, pud->pud_fsgid);
+ if (fsgid == CFS_IDMAP_NOTFOUND) {
CERROR("no mapping for fsgid %u\n", pud->pud_fsgid);
return -EACCES;
}
}
/*
- * Reverse map
- * Do not ignore rootsquash.
+ * Reverse mapping
*/
void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
{
struct ptlrpc_request *req = mdt_info_req(info);
struct md_ucred *uc = mdt_ucred(info);
struct mdt_export_data *med = mdt_req2med(req);
- struct mdt_idmap_table *idmap = med->med_idmap;
- uid_t uid;
- gid_t gid;
+ struct lustre_idmap_table *idmap = med->med_idmap;
if (!med->med_rmtclient)
return;
if (body->valid & OBD_MD_FLUID) {
- if (((uc->mu_valid == UCRED_OLD) ||
- (uc->mu_valid == UCRED_NEW)) &&
- !(uc->mu_squash & SQUASH_UID)) {
- if (body->uid == uc->mu_uid)
- uid = uc->mu_o_uid;
- else if (body->uid == uc->mu_fsuid)
- uid = uc->mu_o_fsuid;
- else
- uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
- } else {
- uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
- }
+ uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 1, body->uid);
- if (uid == MDT_IDMAP_NOTFOUND) {
- uid = med->med_nllu;
+ if (uid == CFS_IDMAP_NOTFOUND) {
+ uid = NOBODY_UID;
if (body->valid & OBD_MD_FLMODE)
body->mode = (body->mode & ~S_IRWXU) |
((body->mode & S_IRWXO) << 6);
}
if (body->valid & OBD_MD_FLGID) {
- if (((uc->mu_valid == UCRED_OLD) ||
- (uc->mu_valid == UCRED_NEW)) &&
- !(uc->mu_squash & SQUASH_GID)) {
- if (body->gid == uc->mu_gid)
- gid = uc->mu_o_gid;
- else if (body->gid == uc->mu_fsgid)
- gid = uc->mu_o_fsgid;
- else
- gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
- } else {
- gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
- }
+ gid_t gid = lustre_idmap_lookup_gid(uc, idmap, 1, body->gid);
- if (gid == MDT_IDMAP_NOTFOUND) {
- gid = med->med_nllg;
+ if (gid == CFS_IDMAP_NOTFOUND) {
+ gid = NOBODY_GID;
if (body->valid & OBD_MD_FLMODE)
body->mode = (body->mode & ~S_IRWXG) |
((body->mode & S_IRWXO) << 3);
}
}
-/* NB: return error if no mapping, so this will look strange:
- * if client hasn't kinit the to map xid for the mapped xid, client
- * will always get -EPERM, and the same for rootsquash case. */
-int mdt_remote_perm_reverse_idmap(struct ptlrpc_request *req,
- struct mdt_remote_perm *perm)
-{
- struct mdt_export_data *med = mdt_req2med(req);
- uid_t uid, fsuid;
- gid_t gid, fsgid;
-
- LASSERT(med->med_rmtclient);
-
- uid = mdt_idmap_lookup_uid(med->med_idmap, 1, perm->rp_uid);
- if (uid == MDT_IDMAP_NOTFOUND) {
- CERROR("no mapping for uid %u\n", perm->rp_uid);
- return -EPERM;
- }
-
- gid = mdt_idmap_lookup_gid(med->med_idmap, 1, perm->rp_gid);
- if (gid == MDT_IDMAP_NOTFOUND) {
- CERROR("no mapping for gid %u\n", perm->rp_gid);
- return -EPERM;
- }
-
- if (perm->rp_uid != perm->rp_fsuid) {
- fsuid = mdt_idmap_lookup_uid(med->med_idmap, 1, perm->rp_fsuid);
- if (fsuid == MDT_IDMAP_NOTFOUND) {
- CERROR("no mapping for fsuid %u\n", perm->rp_fsuid);
- return -EPERM;
- }
- } else {
- fsuid = uid;
- }
-
- if (perm->rp_gid != perm->rp_fsgid) {
- fsgid = mdt_idmap_lookup_gid(med->med_idmap, 1, perm->rp_fsgid);
- if (fsgid == MDT_IDMAP_NOTFOUND) {
- CERROR("no mapping for fsgid %u\n", perm->rp_fsgid);
- return -EPERM;
- }
- } else {
- fsgid = gid;
- }
-
- perm->rp_uid = uid;
- perm->rp_gid = gid;
- perm->rp_fsuid = fsuid;
- perm->rp_fsgid = fsgid;
- return 0;
-}
-
-/* Process remote client and rootsquash */
+/* Do not ignore root_squash for non-setattr case. */
int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
{
struct ptlrpc_request *req = mdt_info_req(info);
struct md_ucred *uc = mdt_ucred(info);
struct lu_attr *attr = &info->mti_attr.ma_attr;
struct mdt_export_data *med = mdt_req2med(req);
- struct mdt_idmap_table *idmap = med->med_idmap;
-
- ENTRY;
+ struct lustre_idmap_table *idmap = med->med_idmap;
if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
- RETURN(-EINVAL);
-
- if (!med->med_rmtclient && (uc->mu_squash == SQUASH_NONE))
- RETURN(0);
+ return -EINVAL;
if (op != REINT_SETATTR) {
if ((attr->la_valid & LA_UID) && (attr->la_uid != -1))
attr->la_uid = uc->mu_fsuid;
- if (op != REINT_CREATE) {
+ /* for S_ISGID, inherit gid from his parent, such work will be
+ * done in cmm/mdd layer, here set all cases as uc->mu_fsgid. */
if ((attr->la_valid & LA_GID) && (attr->la_gid != -1))
attr->la_gid = uc->mu_fsgid;
- } else {
- /* for S_ISGID, inherit gid from his parent */
- if (!(attr->la_mode & S_ISGID) && (attr->la_gid != -1))
- attr->la_gid = uc->mu_fsgid;
- }
} else if (med->med_rmtclient) {
/* NB: -1 case will be handled by mdt_fix_attr() later. */
if ((attr->la_valid & LA_UID) && (attr->la_uid != -1)) {
- uid_t uid;
-
- if (attr->la_uid == uc->mu_o_uid)
- uid = uc->mu_uid;
- else if (attr->la_uid == uc->mu_o_fsuid)
- uid = uc->mu_fsuid;
- else
- uid = mdt_idmap_lookup_uid(idmap, 0,
+ uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 0,
attr->la_uid);
- if (uid == MDT_IDMAP_NOTFOUND) {
+ if (uid == CFS_IDMAP_NOTFOUND) {
CWARN("Deny chown to uid %u\n", attr->la_uid);
- RETURN(-EPERM);
+ return -EPERM;
}
attr->la_uid = uid;
}
if ((attr->la_valid & LA_GID) && (attr->la_gid != -1)) {
- gid_t gid;
-
- if (attr->la_gid == uc->mu_o_gid)
- gid = uc->mu_gid;
- else if (attr->la_gid == uc->mu_o_fsgid)
- gid = uc->mu_fsgid;
- else
- gid = mdt_idmap_lookup_gid(idmap, 0,
+ gid_t gid = lustre_idmap_lookup_gid(uc, idmap, 0,
attr->la_gid);
- if (gid == MDT_IDMAP_NOTFOUND) {
+ if (gid == CFS_IDMAP_NOTFOUND) {
CWARN("Deny chown to gid %u\n", attr->la_gid);
- RETURN(-EPERM);
+ return -EPERM;
}
attr->la_gid = gid;
}
}
- RETURN(0);
+ return 0;
}
#include <lustre_disk.h>
#include <lustre_sec.h>
#include <lvfs.h>
+#include <lustre_idmap.h>
+#include <lustre_eacl.h>
/* Data stored per client in the last_rcvd file. In le32 order. */
unsigned long mdt_client_bitmap[(LR_MAX_CLIENTS >> 3) / sizeof(long)];
struct upcall_cache *mdt_identity_cache;
- struct upcall_cache *mdt_rmtacl_cache;
- /* root squash */
- struct rootsquash_info *mdt_rootsquash_info;
+ /* sptlrpc rules */
+ rwlock_t mdt_sptlrpc_lock;
+ struct sptlrpc_rule_set mdt_sptlrpc_rset;
/* capability keys */
unsigned long mdt_capa_timeout;
void mdt_dump_lmm(int level, const struct lov_mds_md *lmm);
int mdt_check_ucred(struct mdt_thread_info *);
-
int mdt_init_ucred(struct mdt_thread_info *, struct mdt_body *);
-
int mdt_init_ucred_reint(struct mdt_thread_info *);
-
void mdt_exit_ucred(struct mdt_thread_info *);
-int groups_from_list(struct group_info *, gid_t *);
-
-void groups_sort(struct group_info *);
-
/* mdt_idmap.c */
int mdt_init_idmap(struct mdt_thread_info *);
extern struct upcall_cache_ops mdt_identity_upcall_cache_ops;
-struct mdt_identity *mdt_identity_get(struct upcall_cache *, __u32);
+struct md_identity *mdt_identity_get(struct upcall_cache *, __u32);
-void mdt_identity_put(struct upcall_cache *, struct mdt_identity *);
+void mdt_identity_put(struct upcall_cache *, struct md_identity *);
void mdt_flush_identity(struct upcall_cache *, int);
-__u32 mdt_identity_get_setxid_perm(struct mdt_identity *, __u32, lnet_nid_t);
+__u32 mdt_identity_get_perm(struct md_identity *, __u32, lnet_nid_t);
int mdt_pack_remote_perm(struct mdt_thread_info *, struct mdt_object *, void *);
-/* mdt/mdt_rmtacl.c */
-#define MDT_RMTACL_UPCALL_PATH "/usr/sbin/l_facl"
-
-extern struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops;
-
-int mdt_rmtacl_upcall(struct mdt_thread_info *, char *, struct lu_buf *);
-
extern struct lu_context_key mdt_thread_key;
/* debug issues helper starts here*/
static inline void mdt_fail_write(const struct lu_env *env,
* Author: Mike Shaver <shaver@clusterfs.com>
* Author: Nikita Danilov <nikita@clusterfs.com>
* Author: Huang Hua <huanghua@clusterfs.com>
+ * Author: Fan Yong <fanyong@clusterfs.com>
*
*
* This file is part of the Lustre file system, http://www.lustre.org
REC_INIT = 2
} ucred_init_type_t;
-int groups_from_list(struct group_info *ginfo, gid_t *glist)
-{
- int i;
- int count = ginfo->ngroups;
-
- /* fill group_info from gid array */
- for (i = 0; i < ginfo->nblocks; i++) {
- int cp_count = min(NGROUPS_PER_BLOCK, count);
- int off = i * NGROUPS_PER_BLOCK;
- int len = cp_count * sizeof(*glist);
-
- if (memcpy(ginfo->blocks[i], glist + off, len))
- return -EFAULT;
-
- count -= cp_count;
- }
- return 0;
-}
-
-/* groups_sort() is copied from linux kernel! */
-/* a simple shell-metzner sort */
-void groups_sort(struct group_info *group_info)
-{
- int base, max, stride;
- int gidsetsize = group_info->ngroups;
-
- for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
- ; /* nothing */
- stride /= 3;
-
- while (stride) {
- max = gidsetsize - stride;
- for (base = 0; base < max; base++) {
- int left = base;
- int right = left + stride;
- gid_t tmp = GROUP_AT(group_info, right);
-
- while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
- GROUP_AT(group_info, right) =
- GROUP_AT(group_info, left);
- right = left;
- left -= stride;
- }
- GROUP_AT(group_info, right) = tmp;
- }
- stride /= 3;
- }
-}
-
void mdt_exit_ucred(struct mdt_thread_info *info)
{
struct md_ucred *uc = mdt_ucred(info);
}
}
-static int old_init_ucred(struct mdt_thread_info *info,
- struct mdt_body *body)
+/* XXX: root_squash will be redesigned in Lustre 1.7.
+ * Do not root_squash for inter-MDS operations */
+static int mdt_root_squash(struct mdt_thread_info *info)
{
- struct md_ucred *uc = mdt_ucred(info);
- struct mdt_device *mdt = info->mti_mdt;
- struct mdt_identity *identity = NULL;
-
- ENTRY;
-
- uc->mu_valid = UCRED_INVALID;
-
- if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
- /* get identity info of this user */
- identity = mdt_identity_get(mdt->mdt_identity_cache,
- body->fsuid);
- if (!identity) {
- CERROR("Deny access without identity: uid %d\n",
- body->fsuid);
- RETURN(-EACCES);
- }
- }
-
- uc->mu_valid = UCRED_OLD;
- uc->mu_squash = SQUASH_NONE;
- uc->mu_o_uid = uc->mu_uid = body->uid;
- uc->mu_o_gid = uc->mu_gid = body->gid;
- uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
- uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
- uc->mu_suppgids[0] = body->suppgid;
- uc->mu_suppgids[1] = -1;
- if (uc->mu_fsuid)
- uc->mu_cap = body->capability & ~CAP_FS_MASK;
- else
- uc->mu_cap = body->capability;
- uc->mu_ginfo = NULL;
- uc->mu_identity = identity;
-
- RETURN(0);
-}
-
-static int old_init_ucred_reint(struct mdt_thread_info *info)
-{
- struct md_ucred *uc = mdt_ucred(info);
- struct mdt_device *mdt = info->mti_mdt;
- struct mdt_identity *identity = NULL;
-
- ENTRY;
-
- uc->mu_valid = UCRED_INVALID;
-
- if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
- /* get identity info of this user */
- identity = mdt_identity_get(mdt->mdt_identity_cache,
- uc->mu_fsuid);
- if (!identity) {
- CERROR("Deny access without identity: uid %d\n",
- uc->mu_fsuid);
- RETURN(-EACCES);
- }
- }
-
- uc->mu_valid = UCRED_OLD;
- uc->mu_squash = SQUASH_NONE;
- uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
- uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
- if (uc->mu_fsuid)
- uc->mu_cap &= ~CAP_FS_MASK;
- uc->mu_ginfo = NULL;
- uc->mu_identity = identity;
-
- RETURN(0);
-}
-
-static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid)
-{
- struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
- int i;
-
- for (i = 0; i < rsi->rsi_n_nosquash_nids; i++)
- if ((rsi->rsi_nosquash_nids[i] == nid) ||
- (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY))
- return 1;
-
return 0;
}
-static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
- struct ptlrpc_user_desc *pud, lnet_nid_t peernid)
-{
- struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
- if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) ||
- nid_nosquash(mdt, peernid))
- return 0;
-
- CDEBUG(D_SEC, "squash req from "LPX64":"
- "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", peernid,
- pud->pud_uid, pud->pud_gid,
- pud->pud_fsuid, pud->pud_fsgid, pud->pud_cap,
- pud->pud_uid ? pud->pud_uid : rsi->rsi_uid,
- pud->pud_uid ? pud->pud_gid : rsi->rsi_gid,
- pud->pud_fsuid ? pud->pud_fsuid : rsi->rsi_uid,
- pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid,
- pud->pud_cap & ~CAP_FS_MASK);
-
- if (rsi->rsi_uid) {
- if (!pud->pud_uid) {
- ucred->mu_uid = rsi->rsi_uid;
- ucred->mu_squash |= SQUASH_UID;
- } else {
- ucred->mu_uid = pud->pud_uid;
- }
-
- if (!pud->pud_fsuid) {
- ucred->mu_fsuid = rsi->rsi_uid;
- ucred->mu_squash |= SQUASH_UID;
- } else {
- ucred->mu_fsuid = pud->pud_fsuid;
- }
- } else {
- ucred->mu_uid = pud->pud_uid;
- ucred->mu_fsuid = pud->pud_fsuid;
- }
-
- if (rsi->rsi_gid) {
- int i;
-
- if (!pud->pud_gid) {
- ucred->mu_gid = rsi->rsi_gid;
- ucred->mu_squash |= SQUASH_GID;
- } else {
- ucred->mu_gid = pud->pud_gid;
- }
-
- if (!pud->pud_fsgid) {
- ucred->mu_fsgid = rsi->rsi_gid;
- ucred->mu_squash |= SQUASH_GID;
- } else {
- ucred->mu_fsgid = pud->pud_fsgid;
- }
-
- for (i = 0; i < 2; i++) {
- if (!ucred->mu_suppgids[i]) {
- ucred->mu_suppgids[i] = rsi->rsi_gid;
- ucred->mu_squash |= SQUASH_GID;
- }
- }
-
- for (i = 0; i < pud->pud_ngroups; i++) {
- if (!pud->pud_groups[i]) {
- pud->pud_groups[i] = rsi->rsi_gid;
- ucred->mu_squash |= SQUASH_GID;
- }
- }
- } else {
- ucred->mu_gid = pud->pud_gid;
- ucred->mu_fsgid = pud->pud_fsgid;
- }
-
- return 1;
-}
-
static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
void *buf)
{
struct mdt_device *mdt = info->mti_mdt;
struct ptlrpc_user_desc *pud = req->rq_user_desc;
struct md_ucred *ucred = mdt_ucred(info);
- struct mdt_identity *identity = NULL;
lnet_nid_t peernid = req->rq_peer.nid;
- __u32 setxid_perm = 0;
+ __u32 perm = 0;
int setuid;
int setgid;
int rc = 0;
RETURN(-EACCES);
if (req->rq_auth_mapped_uid != pud->pud_uid) {
- CERROR("remote client "LPU64": auth uid %u "
+ CERROR("remote client "LPU64": auth/mapped uid %u/%u "
"while client claim %u:%u/%u:%u\n",
- peernid, req->rq_auth_uid, pud->pud_uid,
- pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
+ peernid, req->rq_auth_uid,
+ req->rq_auth_mapped_uid,
+ pud->pud_uid, pud->pud_gid,
+ pud->pud_fsuid, pud->pud_fsgid);
RETURN(-EACCES);
}
} else {
"enabled!\n");
RETURN(-EACCES);
} else {
- setxid_perm |= LUSTRE_SETGRP_PERM;
- goto check_squash;
+ ucred->mu_identity = NULL;
+ perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
+ CFS_SETGRP_PERM;
}
- }
-
- identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
- if (!identity) {
- CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
+ } else {
+ ucred->mu_identity = mdt_identity_get(mdt->mdt_identity_cache,
+ pud->pud_uid);
+ if (!ucred->mu_identity) {
+ CERROR("Deny access without identity: uid %d\n",
+ pud->pud_uid);
RETURN(-EACCES);
- }
-
- setxid_perm = mdt_identity_get_setxid_perm(identity,
+ } else {
+ perm = mdt_identity_get_perm(ucred->mu_identity,
med->med_rmtclient,
peernid);
+ }
+ }
/* find out the setuid/setgid attempt */
setuid = (pud->pud_uid != pud->pud_fsuid);
- setgid = (pud->pud_gid != pud->pud_fsgid ||
- pud->pud_gid != identity->mi_gid);
+ setgid = ((pud->pud_gid != pud->pud_fsgid) ||
+ (ucred->mu_identity &&
+ (pud->pud_gid != ucred->mu_identity->mi_gid)));
/* check permission of setuid */
- if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
+ if (setuid && !(perm & CFS_SETUID_PERM)) {
CWARN("mdt blocked setuid attempt (%u -> %u) from "
LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
GOTO(out, rc = -EACCES);
}
/* check permission of setgid */
- if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
+ if (setgid && !(perm & CFS_SETGID_PERM)) {
CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
"from "LPX64"\n", pud->pud_uid, pud->pud_gid,
- pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
- peernid);
+ pud->pud_fsuid, pud->pud_fsgid,
+ ucred->mu_identity->mi_gid, peernid);
GOTO(out, rc = -EACCES);
}
-check_squash:
- /* FIXME: The exact behavior of root_squash is not defined. */
- ucred->mu_squash = SQUASH_NONE;
- if (mdt_squash_root(mdt, ucred, pud, peernid) == 0) {
- ucred->mu_uid = pud->pud_uid;
- ucred->mu_gid = pud->pud_gid;
- ucred->mu_fsuid = pud->pud_fsuid;
- ucred->mu_fsgid = pud->pud_fsgid;
- }
-
- /* remove fs privilege for non-root user */
- if (ucred->mu_fsuid)
- ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
- else
- ucred->mu_cap = pud->pud_cap;
-
/*
* NB: remote client not allowed to setgroups anyway.
*/
- if (!med->med_rmtclient && pud->pud_ngroups &&
- (setxid_perm & LUSTRE_SETGRP_PERM)) {
- struct group_info *ginfo;
-
+ if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
+ if (pud->pud_ngroups) {
/* setgroups for local client */
- ginfo = groups_alloc(pud->pud_ngroups);
- if (!ginfo) {
+ ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
+ if (!ucred->mu_ginfo) {
CERROR("failed to alloc %d groups\n",
pud->pud_ngroups);
GOTO(out, rc = -ENOMEM);
}
- groups_from_list(ginfo, pud->pud_groups);
- groups_sort(ginfo);
- ucred->mu_ginfo = ginfo;
+
+ lustre_groups_from_list(ucred->mu_ginfo,
+ pud->pud_groups);
+ lustre_groups_sort(ucred->mu_ginfo);
} else {
ucred->mu_ginfo = NULL;
}
+ } else {
+ ucred->mu_suppgids[0] = -1;
+ ucred->mu_suppgids[1] = -1;
+ ucred->mu_ginfo = NULL;
+ }
- ucred->mu_identity = identity;
+ ucred->mu_uid = pud->pud_uid;
+ ucred->mu_gid = pud->pud_gid;
+ ucred->mu_fsuid = pud->pud_fsuid;
+ ucred->mu_fsgid = pud->pud_fsgid;
+
+ /* XXX: need to process root_squash here. */
+ mdt_root_squash(info);
+
+ /* remove fs privilege for non-root user */
+ if (ucred->mu_fsuid)
+ ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
+ else
+ ucred->mu_cap = pud->pud_cap;
ucred->mu_valid = UCRED_NEW;
EXIT;
out:
- if (rc && identity)
- mdt_identity_put(mdt->mdt_identity_cache, identity);
+ if (rc) {
+ if (ucred->mu_ginfo) {
+ groups_free(ucred->mu_ginfo);
+ ucred->mu_ginfo = NULL;
+ }
+ if (ucred->mu_identity) {
+ mdt_identity_put(mdt->mdt_identity_cache,
+ ucred->mu_identity);
+ ucred->mu_identity = NULL;
+ }
+ }
return rc;
}
struct mdt_device *mdt = info->mti_mdt;
struct ptlrpc_user_desc *pud = req->rq_user_desc;
struct md_ucred *ucred = mdt_ucred(info);
- struct mdt_identity *identity;
+ struct md_identity *identity = NULL;
lnet_nid_t peernid = req->rq_peer.nid;
+ __u32 perm = 0;
+ int setuid;
+ int setgid;
+ int rc = 0;
ENTRY;
if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
RETURN(0);
- if (!req->rq_user_desc)
+ if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
RETURN(0);
/* sanity check: if we use strong authentication, we expect the
* uid which client claimed is true */
- if (req->rq_auth_gss) {
if (med->med_rmtclient) {
if (req->rq_auth_mapped_uid == INVALID_UID) {
CWARN("remote user not mapped, deny access!\n");
RETURN(-EACCES);
if (req->rq_auth_mapped_uid != pud->pud_uid) {
- CERROR("remote client "LPU64": auth uid %u "
+ CERROR("remote client "LPU64": auth/mapped uid %u/%u "
"while client claim %u:%u/%u:%u\n",
- peernid, req->rq_auth_uid, pud->pud_uid,
- pud->pud_gid, pud->pud_fsuid,
- pud->pud_fsgid);
+ peernid, req->rq_auth_uid,
+ req->rq_auth_mapped_uid,
+ pud->pud_uid, pud->pud_gid,
+ pud->pud_fsuid, pud->pud_fsgid);
RETURN(-EACCES);
}
} else {
RETURN(-EACCES);
}
}
- }
if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
if (med->med_rmtclient) {
- CERROR("remote client must run with "
- "identity_get enabled!\n");
+ CERROR("remote client must run with identity_get "
+ "enabled!\n");
RETURN(-EACCES);
}
- } else {
+ RETURN(0);
+ }
+
+ identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
+ if (!identity) {
+ CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
+ RETURN(-EACCES);
+ }
+
+ perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
+ /* find out the setuid/setgid attempt */
+ setuid = (pud->pud_uid != pud->pud_fsuid);
+ setgid = (pud->pud_gid != pud->pud_fsgid ||
+ pud->pud_gid != identity->mi_gid);
+
+ /* check permission of setuid */
+ if (setuid && !(perm & CFS_SETUID_PERM)) {
+ CWARN("mdt blocked setuid attempt (%u -> %u) from "
+ LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
+ GOTO(out, rc = -EACCES);
+ }
+
+ /* check permission of setgid */
+ if (setgid && !(perm & CFS_SETGID_PERM)) {
+ CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
+ "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
+ pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
+ peernid);
+ GOTO(out, rc = -EACCES);
+ }
+
+ EXIT;
+
+out:
+ mdt_identity_put(mdt->mdt_identity_cache, identity);
+ return rc;
+}
+
+static int old_init_ucred(struct mdt_thread_info *info,
+ struct mdt_body *body)
+{
+ struct md_ucred *uc = mdt_ucred(info);
+ struct mdt_device *mdt = info->mti_mdt;
+ struct md_identity *identity = NULL;
+
+ ENTRY;
+
+ uc->mu_valid = UCRED_INVALID;
+ uc->mu_o_uid = uc->mu_uid = body->uid;
+ uc->mu_o_gid = uc->mu_gid = body->gid;
+ uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
+ uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
+ uc->mu_suppgids[0] = body->suppgid;
+ uc->mu_suppgids[1] = -1;
+ uc->mu_ginfo = NULL;
+ if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
identity = mdt_identity_get(mdt->mdt_identity_cache,
- pud->pud_uid);
+ uc->mu_fsuid);
if (!identity) {
CERROR("Deny access without identity: uid %d\n",
- pud->pud_uid);
+ uc->mu_fsuid);
RETURN(-EACCES);
}
+ }
+ uc->mu_identity = identity;
+
+ /* XXX: need to process root_squash here. */
+ mdt_root_squash(info);
+
+ /* remove fs privilege for non-root user */
+ if (uc->mu_fsuid)
+ uc->mu_cap = body->capability & ~CAP_FS_MASK;
+ else
+ uc->mu_cap = body->capability;
+ uc->mu_valid = UCRED_OLD;
+
+ RETURN(0);
+}
+
+static int old_init_ucred_reint(struct mdt_thread_info *info)
+{
+ struct md_ucred *uc = mdt_ucred(info);
+ struct mdt_device *mdt = info->mti_mdt;
+ struct md_identity *identity = NULL;
+
+ ENTRY;
- mdt_identity_put(mdt->mdt_identity_cache, identity);
+ uc->mu_valid = UCRED_INVALID;
+ uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
+ uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
+ uc->mu_ginfo = NULL;
+ if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
+ identity = mdt_identity_get(mdt->mdt_identity_cache,
+ uc->mu_fsuid);
+ if (!identity) {
+ CERROR("Deny access without identity: uid %d\n",
+ uc->mu_fsuid);
+ RETURN(-EACCES);
+ }
}
+ uc->mu_identity = identity;
+
+ /* XXX: need to process root_squash here. */
+ mdt_root_squash(info);
+
+ /* remove fs privilege for non-root user */
+ if (uc->mu_fsuid)
+ uc->mu_cap &= ~CAP_FS_MASK;
+ uc->mu_valid = UCRED_OLD;
RETURN(0);
}
GOTO(out, rc = -EINVAL);
}
- if (sparam.idd_nperms > N_SETXID_PERMS_MAX) {
+ if (sparam.idd_nperms > N_PERMS_MAX) {
CERROR("%s: perm count %d more than maximum %d\n",
- obd->obd_name, sparam.idd_nperms, N_SETXID_PERMS_MAX);
+ obd->obd_name, sparam.idd_nperms, N_PERMS_MAX);
GOTO(out, rc = -EINVAL);
}
return rc ?: count;
}
-static int lprocfs_rd_rmtacl_expire(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
- *eof = 1;
- return snprintf(page, count, "%lu\n",
- mdt->mdt_rmtacl_cache->uc_entry_expire / HZ);
-}
-
-static int lprocfs_wr_rmtacl_expire(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- int rc, val;
-
- rc = lprocfs_write_helper(buffer, count, &val);
- if (rc)
- return rc;
-
- mdt->mdt_rmtacl_cache->uc_entry_expire = val * HZ;
- return count;
-}
-
-static int lprocfs_rd_rmtacl_acquire_expire(char *page, char **start,
- off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
- *eof = 1;
- return snprintf(page, count, "%lu\n",
- mdt->mdt_rmtacl_cache->uc_acquire_expire / HZ);
-}
-
-static int lprocfs_wr_rmtacl_acquire_expire(struct file *file,
- const char *buffer,
- unsigned long count,
- void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- int rc, val;
-
- rc = lprocfs_write_helper(buffer, count, &val);
- if (rc)
- return rc;
-
- mdt->mdt_rmtacl_cache->uc_acquire_expire = val * HZ;
- return count;
-}
-
-static int lprocfs_rd_rmtacl_upcall(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
- *eof = 1;
- return snprintf(page, count, "%s\n",
- mdt->mdt_rmtacl_cache->uc_upcall);
-}
-
-static int lprocfs_wr_rmtacl_upcall(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- struct upcall_cache *hash = mdt->mdt_rmtacl_cache;
- char kernbuf[UC_CACHE_UPCALL_MAXPATH] = { '\0' };
-
- if (count >= UC_CACHE_UPCALL_MAXPATH) {
- CERROR("%s: remote ACL upcall too long\n", obd->obd_name);
- return -EINVAL;
- }
-
- if (copy_from_user(kernbuf, buffer,
- min(count, UC_CACHE_UPCALL_MAXPATH - 1)))
- return -EFAULT;
-
- /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
- sscanf(kernbuf, "%s", hash->uc_upcall);
-
- if (strcmp(hash->uc_name, obd->obd_name) != 0)
- CWARN("%s: write to upcall name %s\n",
- obd->obd_name, hash->uc_upcall);
- CWARN("%s: remote ACL upcall set to %s\n", obd->obd_name, hash->uc_upcall);
-
- return count;
-}
-
-static int lprocfs_wr_rmtacl_info(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- struct rmtacl_downcall_data sparam, *param = &sparam;
- int size = 0, rc = 0;
-
- if (count < sizeof(*param)) {
- CERROR("%s: invalid data size %lu\n", obd->obd_name, count);
- return count;
- }
-
- if (copy_from_user(&sparam, buffer, sizeof(sparam))) {
- CERROR("%s: bad remote acl data\n", obd->obd_name);
- GOTO(out, rc = -EFAULT);
- }
-
- if (sparam.add_magic != RMTACL_DOWNCALL_MAGIC) {
- CERROR("%s: MDT remote acl downcall bad params\n", obd->obd_name);
- GOTO(out, rc = -EINVAL);
- }
-
- if (sparam.add_buflen) {
- size = offsetof(struct rmtacl_downcall_data,
- add_buf[sparam.add_buflen]);
- OBD_ALLOC(param, size);
- if (!param) {
- CERROR("%s: fail to alloc %d bytes for ino "LPU64"\n",
- obd->obd_name, size, sparam.add_key);
- param = &sparam;
- param->add_buflen = 0;
- } else if (copy_from_user(param, buffer, size)) {
- CERROR("%s: ino "LPU64" bad remote acl data\n",
- obd->obd_name, sparam.add_key);
- OBD_FREE(param, size);
- param = &sparam;
- param->add_buflen = 0;
- }
- }
-
- rc = upcall_cache_downcall(mdt->mdt_rmtacl_cache, 0, param->add_key,
- param);
-
-out:
- if (param && (param != &sparam))
- OBD_FREE(param, size);
-
- return rc ?: count;
-}
-
-static int lprocfs_rd_rootsquash_uid(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
- *eof = 1;
- return snprintf(page, count, "%u\n",
- rsi ? rsi->rsi_uid : 0);
-}
-
-static int lprocfs_wr_rootsquash_uid(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- int val, rc;
-
- rc = lprocfs_write_helper(buffer, count, &val);
- if (rc)
- return rc;
-
- if (!mdt->mdt_rootsquash_info)
- OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
- if (!mdt->mdt_rootsquash_info)
- return -ENOMEM;
-
- mdt->mdt_rootsquash_info->rsi_uid = val;
- return count;
-}
-
-static int lprocfs_rd_rootsquash_gid(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
- *eof = 1;
- return snprintf(page, count, "%u\n",
- rsi ? rsi->rsi_gid : 0);
-}
-
-static int lprocfs_wr_rootsquash_gid(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- int val, rc;
-
- rc = lprocfs_write_helper(buffer, count, &val);
- if (rc)
- return rc;
-
- if (!mdt->mdt_rootsquash_info)
- OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
- if (!mdt->mdt_rootsquash_info)
- return -ENOMEM;
-
- mdt->mdt_rootsquash_info->rsi_gid = val;
- return count;
-}
-
-static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
- int i, ret;
-
- ret = snprintf(page, count, "rootsquash skip list:\n");
- for (i = 0; rsi && (i < rsi->rsi_n_nosquash_nids); i++) {
- ret += snprintf(page + ret, count - ret, "%s\n",
- libcfs_nid2str(rsi->rsi_nosquash_nids[i]));
- }
-
- *eof = 1;
- return ret;
-}
-
-static inline void remove_newline(char *str)
-{
- int len = strlen(str);
-
- if (str[len - 1] == '\n')
- str[len - 1] = '\0';
-}
-
-/* XXX: This macro is copied from lnet/libcfs/nidstring.c */
-#define LNET_NIDSTR_SIZE 32 /* size of each one (see below for usage) */
-
-static void do_process_nosquash_nids(struct mdt_device *m, char *buf)
-{
- struct rootsquash_info *rsi = m->mdt_rootsquash_info;
- char str[LNET_NIDSTR_SIZE], *end;
- lnet_nid_t nid;
-
- LASSERT(rsi);
- rsi->rsi_n_nosquash_nids = 0;
- while (rsi->rsi_n_nosquash_nids < N_NOSQUASH_NIDS) {
- end = strchr(buf, ',');
- memset(str, 0, sizeof(str));
- if (end)
- strncpy(str, buf, min_t(int, sizeof(str), end - buf));
- else
- strncpy(str, buf, min_t(int, sizeof(str), strlen(buf)));
-
- if (!strcmp(str, "*")) {
- nid = LNET_NID_ANY;
- } else {
- nid = libcfs_str2nid(str);
- if (nid == LNET_NID_ANY)
- goto ignore;
- }
- rsi->rsi_nosquash_nids[rsi->rsi_n_nosquash_nids++] = nid;
-ignore:
- if (!end || (*(end + 1) == 0))
- return;
- buf = end + 1;
- }
-}
-
-static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- struct obd_device *obd = data;
- struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
- char skips[LNET_NIDSTR_SIZE * N_NOSQUASH_NIDS] = "";
- unsigned long size = sizeof(skips);
-
- if (count > size) {
- CERROR("parameter exceeds max limit %lu\n", size);
- return -EINVAL;
- }
-
- if (copy_from_user(skips, buffer, min(size, count)))
- return -EFAULT;
-
- if (!mdt->mdt_rootsquash_info)
- OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
- if (!mdt->mdt_rootsquash_info)
- return -ENOMEM;
-
- remove_newline(skips);
- do_process_nosquash_nids(mdt, skips);
- return count;
-}
-
/* for debug only */
static int lprocfs_rd_capa(char *page, char **start, off_t off,
int count, int *eof, void *data)
lprocfs_wr_identity_upcall, 0 },
{ "identity_flush", 0, lprocfs_wr_identity_flush, 0 },
{ "identity_info", 0, lprocfs_wr_identity_info, 0 },
- { "rmtacl_expire", lprocfs_rd_rmtacl_expire,
- lprocfs_wr_rmtacl_expire, 0 },
- { "rmtacl_acquire_expire", lprocfs_rd_rmtacl_acquire_expire,
- lprocfs_wr_rmtacl_acquire_expire, 0 },
- { "rmtacl_upcall", lprocfs_rd_rmtacl_upcall,
- lprocfs_wr_rmtacl_upcall, 0 },
- { "rmtacl_info", 0, lprocfs_wr_rmtacl_info, 0 },
- { "rootsquash_uid", lprocfs_rd_rootsquash_uid,
- lprocfs_wr_rootsquash_uid, 0 },
- { "rootsquash_gid", lprocfs_rd_rootsquash_gid,
- lprocfs_wr_rootsquash_gid, 0 },
- { "nosquash_nids", lprocfs_rd_nosquash_nids,
- lprocfs_wr_nosquash_nids, 0 },
{ "capa", lprocfs_rd_capa,
lprocfs_wr_capa, 0 },
{ "capa_timeout", lprocfs_rd_capa_timeout,
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
- * Author: Lai Siyao <lsy@clusterfs.com>
- * Author: Fan Yong <fanyong@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef EXPORT_SYMTAB
-#define EXPORT_SYMTAB
-#endif
-#define DEBUG_SUBSYSTEM S_MDS
-
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/kmod.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/version.h>
-#include <linux/unistd.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-#include <asm/segment.h>
-
-#include <libcfs/kp30.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_lib.h>
-#include <lustre_ucache.h>
-
-#include "mdt_internal.h"
-
-#define MAX_CMD_LEN 256
-
-static __u64 rmtacl_key = 0;
-static spinlock_t rmtacl_key_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * For remote acl operation, do NOT cache!
- * Use different key for each remote acl operation.
- */
-static __u64 mdt_rmtacl_getkey(void)
-{
- __u64 key;
-
- spin_lock(&rmtacl_key_lock);
- key = ++rmtacl_key;
- spin_unlock(&rmtacl_key_lock);
-
- return key;
-}
-
-static void mdt_rmtacl_entry_init(struct upcall_cache_entry *entry, void *args)
-{
- struct rmtacl_upcall_data *data = args;
- struct mdt_rmtacl *acl = &entry->u.acl;
- char *cmd;
-
- acl->ra_uid = data->aud_uid;
- acl->ra_gid = data->aud_gid;
- /* we use address of this cache entry as handle */
- acl->ra_handle = (__u32)entry;
- OBD_ALLOC(cmd, strlen(data->aud_cmd) + 1);
- if (!cmd)
- return; /* upcall will fail later! */
-
- strcpy(cmd, data->aud_cmd);
- acl->ra_cmd = cmd;
-}
-
-static void mdt_rmtacl_entry_free(struct upcall_cache *cache,
- struct upcall_cache_entry *entry)
-{
- struct mdt_rmtacl *acl = &entry->u.acl;
- int len;
-
- if (acl->ra_cmd) {
- len = strlen(acl->ra_cmd) + 1;
- OBD_FREE(acl->ra_cmd, len);
- }
-
- if (acl->ra_buf) {
- len = strlen(acl->ra_buf) + 1;
- OBD_FREE(acl->ra_buf, len);
- }
-}
-
-static int mdt_rmtacl_upcall_compare(struct upcall_cache *cache,
- struct upcall_cache_entry *entry,
- __u64 key, void *args)
-{
- struct rmtacl_upcall_data *data = args;
-
- LASSERT(entry && data);
- LASSERT(entry->u.acl.ra_cmd && data->aud_cmd);
- return strncmp(entry->u.acl.ra_cmd, data->aud_cmd, MAX_CMD_LEN);
-}
-
-static int mdt_rmtacl_downcall_compare(struct upcall_cache *cache,
- struct upcall_cache_entry *entry,
- __u64 key, void *args)
-{
- struct rmtacl_downcall_data *data = args;
-
- return entry->u.acl.ra_handle - data->add_handle;
-}
-
-static int mdt_rmtacl_do_upcall(struct upcall_cache *cache,
- struct upcall_cache_entry *entry)
-{
- struct mdt_rmtacl *acl = &entry->u.acl;
- char uidstr[8] = "";
- char gidstr[8] = "";
- char handle[20] = "";
- char keystr[20] = "";
- char *argv[] = {
- [0] = cache->uc_upcall,
- [1] = uidstr,
- [2] = gidstr,
- [3] = cache->uc_name,
- [4] = keystr,
- [5] = handle,
- [6] = acl->ra_cmd,
- [7] = NULL
- };
- char *envp[] = {
- [0] = "HOME=/",
- [1] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
- [2] = NULL
- };
- int rc;
- ENTRY;
-
- if (!acl->ra_cmd)
- RETURN(-ENOMEM);
-
- snprintf(uidstr, sizeof(uidstr), "%u", acl->ra_uid);
- snprintf(gidstr, sizeof(gidstr), "%u", acl->ra_gid);
- snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
- snprintf(handle, sizeof(handle), "%u", acl->ra_handle);
-
- LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
-
- CDEBUG(D_INFO, "%s: remote acl upcall %s %s %s %s %s %s %s\n",
- cache->uc_name, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6]);
-
- rc = USERMODEHELPER(argv[0], argv, envp);
- if (rc < 0) {
- CERROR("%s: error invoking upcall %s %s %s %s %s %s %s: rc %d; "
- "check /proc/fs/lustre/mdt/%s/rmtacl_upcall\n",
- cache->uc_name, argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6], rc, cache->uc_name);
- } else {
- CDEBUG(D_HA, "%s: invoked upcall %s %s %s %s %s %s %s\n",
- cache->uc_name, argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6]);
- rc = 0;
- }
- RETURN(rc);
-}
-
-static int mdt_rmtacl_parse_downcall(struct upcall_cache *cache,
- struct upcall_cache_entry *entry,
- void *args)
-{
- struct mdt_rmtacl *acl = &entry->u.acl;
- struct rmtacl_downcall_data *data;
- char *buf;
- int len;
- ENTRY;
-
- data = (struct rmtacl_downcall_data *)args;
- LASSERT(data);
-
- len = strlen(data->add_buf) + 1;
- OBD_ALLOC(buf, len);
- if (!buf)
- RETURN(-ENOMEM);
-
- memcpy(buf, data->add_buf, len);
- acl->ra_buf = buf;
-
- CDEBUG(D_OTHER, "parse mdt acl@%p: %s %s\n",
- acl, acl->ra_cmd, acl->ra_buf);
-
- RETURN(0);
-}
-
-struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops = {
- .init_entry = mdt_rmtacl_entry_init,
- .free_entry = mdt_rmtacl_entry_free,
- .upcall_compare = mdt_rmtacl_upcall_compare,
- .downcall_compare = mdt_rmtacl_downcall_compare,
- .do_upcall = mdt_rmtacl_do_upcall,
- .parse_downcall = mdt_rmtacl_parse_downcall,
-};
-
-int mdt_rmtacl_upcall(struct mdt_thread_info *info, char *cmd,
- struct lu_buf *buf)
-{
- struct mdt_device *mdt = info->mti_mdt;
- struct md_ucred *uc = mdt_ucred(info);
- struct rmtacl_upcall_data data;
- struct upcall_cache_entry *entry;
- __u64 key;
- int rc = 0;
- ENTRY;
-
- data.aud_uid = uc->mu_fsuid;
- data.aud_gid = uc->mu_fsgid;
- data.aud_cmd = cmd;
-
- key = mdt_rmtacl_getkey();
-
- entry = upcall_cache_get_entry(mdt->mdt_rmtacl_cache, key, &data);
- if (IS_ERR(entry))
- GOTO(out, rc = PTR_ERR(entry));
-
- if (buf->lb_len <= strlen(entry->u.acl.ra_buf))
- GOTO(out, rc = -EFAULT);
-
- memcpy(buf->lb_buf, entry->u.acl.ra_buf, strlen(entry->u.acl.ra_buf));
- /* remote acl operation expire at once! */
- UC_CACHE_SET_EXPIRED(entry);
- upcall_cache_put_entry(mdt->mdt_rmtacl_cache, entry);
-
-out:
- if (rc)
- sprintf(buf->lb_buf, "server processing error: %d\n", rc);
- RETURN(0);
-}
!strncmp(xattr_name, user_string, sizeof(user_string) - 1))
RETURN(-EOPNOTSUPP);
- if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
- size = RMTACL_SIZE_MAX;
- else
size = mo_xattr_get(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL, xattr_name);
RETURN(size);
}
-static int do_remote_getfacl(struct mdt_thread_info *info, struct lu_buf *buf)
-{
- struct ptlrpc_request *req = mdt_info_req(info);
- char *cmd;
- int rc;
- ENTRY;
-
- if (!buf->lb_buf || (buf->lb_len != RMTACL_SIZE_MAX))
- RETURN(-EINVAL);
-
- cmd = req_capsule_client_get(&info->mti_pill, &RMF_EADATA);
- if (!cmd) {
- CERROR("missing getfacl command!\n");
- RETURN(-EFAULT);
- }
-
- rc = mdt_rmtacl_upcall(info, cmd, buf);
- if (rc)
- CERROR("remote acl upcall failed: %d\n", rc);
-
- lustre_shrink_reply(req, REPLY_REC_OFF + 1, strlen(buf->lb_buf) + 1, 0);
- RETURN(rc ?: strlen(buf->lb_buf) + 1);
-}
-
int mdt_getxattr(struct mdt_thread_info *info)
{
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct mdt_export_data *med = mdt_req2med(req);
+ struct md_ucred *uc = mdt_ucred(info);
struct mdt_body *reqbody;
struct mdt_body *repbody = NULL;
struct md_object *next;
if (rc)
RETURN(err_serious(rc));
+ next = mdt_object_child(info->mti_object);
+
+ if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL) {
+ __u32 perm = mdt_identity_get_perm(uc->mu_identity,
+ med->med_rmtclient,
+ req->rq_peer.nid);
+
+ LASSERT(med->med_rmtclient);
+ if (!(perm & CFS_RMTACL_PERM))
+ GOTO(out, rc = err_serious(-EPERM));
+
+ rc = mo_permission(info->mti_env, NULL, next, NULL,
+ MAY_RGETFACL);
+ if (rc)
+ GOTO(out, rc = err_serious(rc));
+ }
+
easize = mdt_getxattr_pack_reply(info);
if (easize < 0)
GOTO(out, rc = err_serious(easize));
buf = &info->mti_buf;
buf->lb_buf = req_capsule_server_get(&info->mti_pill, &RMF_EADATA);
buf->lb_len = easize;
- next = mdt_object_child(info->mti_object);
if (info->mti_body->valid & OBD_MD_FLXATTR) {
+ int flags = CFS_IC_NOTHING;
char *xattr_name = req_capsule_client_get(&info->mti_pill,
&RMF_NAME);
CDEBUG(D_INODE, "getxattr %s\n", xattr_name);
- if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
- rc = do_remote_getfacl(info, buf);
- else
rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
-
- if (rc < 0)
+ if (rc < 0) {
CERROR("getxattr failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ if (info->mti_body->valid &
+ (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
+ flags = CFS_IC_ALL;
+ else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
+ flags = CFS_IC_MAPPED;
+
+ if (rc > 0 && flags != CFS_IC_NOTHING) {
+ int rc1;
+
+ LASSERT(med->med_rmtclient);
+ rc1 = lustre_posix_acl_xattr_id2client(uc,
+ med->med_idmap,
+ (posix_acl_xattr_header *)(buf->lb_buf),
+ rc, flags);
+ if (unlikely(rc1 < 0))
+ rc = rc1;
+ }
} else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
CDEBUG(D_INODE, "listxattr\n");
return rc;
}
-/* return EADATA length to the caller. negative value means error */
-static int mdt_setxattr_pack_reply(struct mdt_thread_info * info)
-{
- struct req_capsule *pill = &info->mti_pill ;
- __u64 valid = info->mti_body->valid;
- int rc = 0, rc1;
-
- if ((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) {
- char *xattr_name;
-
- xattr_name = req_capsule_client_get(pill, &RMF_NAME);
- if (!xattr_name)
- return -EFAULT;
-
- if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
- rc = RMTACL_SIZE_MAX;
- }
-
- req_capsule_set_size(pill, &RMF_EADATA, RCL_SERVER, rc);
-
- rc1 = req_capsule_pack(pill);
-
- return rc = rc1 ? rc1 : rc;
-}
-
-static int do_remote_setfacl(struct mdt_thread_info *info)
+static int mdt_rmtlsetfacl(struct mdt_thread_info *info, char *xattr_name,
+ ext_acl_xattr_header *header,
+ posix_acl_xattr_header **out)
{
struct ptlrpc_request *req = mdt_info_req(info);
+ struct mdt_export_data *med = mdt_req2med(req);
+ struct md_ucred *uc = mdt_ucred(info);
+ struct md_object *next = mdt_object_child(info->mti_object);
struct lu_buf *buf = &info->mti_buf;
- char *cmd;
int rc;
ENTRY;
- cmd = req_capsule_client_get(&info->mti_pill, &RMF_EADATA);
- if (!cmd) {
- CERROR("missing setfacl command!\n");
- RETURN(-EFAULT);
+ rc = lustre_ext_acl_xattr_id2server(uc, med->med_idmap, header);
+ if (rc)
+ RETURN(rc);
+
+ rc = mo_xattr_get(info->mti_env, next, &LU_BUF_NULL, xattr_name);
+ if (rc == -ENODATA)
+ rc = 0;
+ else if (rc < 0)
+ RETURN(rc);
+
+ buf->lb_len = rc;
+ if (buf->lb_len > 0) {
+ OBD_ALLOC(buf->lb_buf, buf->lb_len);
+ if (unlikely(buf->lb_buf == NULL))
+ RETURN(-ENOMEM);
+
+ rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
+ if (rc < 0) {
+ CERROR("getxattr failed: %d\n", rc);
+ GOTO(_out, rc);
}
+ } else
+ buf->lb_buf = NULL;
- buf->lb_buf = req_capsule_server_get(&info->mti_pill, &RMF_EADATA);
- LASSERT(buf->lb_buf);
- buf->lb_len = RMTACL_SIZE_MAX;
+ rc = lustre_acl_xattr_merge2posix((posix_acl_xattr_header *)(buf->lb_buf),
+ buf->lb_len, header, out);
+ EXIT;
- rc = mdt_rmtacl_upcall(info, cmd, buf);
- if (rc)
- CERROR("remote acl upcall failed: %d\n", rc);
+_out:
+ if (rc <= 0 && buf->lb_buf != NULL)
+ OBD_FREE(buf->lb_buf, buf->lb_len);
- lustre_shrink_reply(req, REPLY_REC_OFF, strlen(buf->lb_buf) + 1, 0);
- RETURN(rc);
+ return rc;
}
int mdt_setxattr(struct mdt_thread_info *info)
{
struct ptlrpc_request *req = mdt_info_req(info);
+ struct mdt_export_data *med = mdt_req2med(req);
+ struct md_ucred *uc = mdt_ucred(info);
struct mdt_body *reqbody;
const char user_string[] = "user.";
const char trust_string[] = "trusted.";
struct lu_buf *buf = &info->mti_buf;
__u64 valid = body->valid;
char *xattr_name;
- int xattr_len;
+ int xattr_len = 0;
__u64 lockpart;
int rc;
+ posix_acl_xattr_header *new_xattr = NULL;
ENTRY;
CDEBUG(D_INODE, "setxattr "DFID"\n", PFID(&body->fid1));
if (rc)
RETURN(err_serious(rc));
- rc = mdt_setxattr_pack_reply(info);
+ if (valid & OBD_MD_FLRMTRSETFACL) {
+ __u32 perm = mdt_identity_get_perm(uc->mu_identity,
+ med->med_rmtclient,
+ req->rq_peer.nid);
+
+ LASSERT(med->med_rmtclient);
+ if (!(perm & CFS_RMTACL_PERM))
+ GOTO(out, rc = err_serious(-EPERM));
+ }
+
+ rc = req_capsule_pack(pill);
if (rc < 0)
GOTO(out, rc = err_serious(rc));
CDEBUG(D_INODE, "%s xattr %s\n",
body->valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);
- if (((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) &&
- (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))) {
- rc = do_remote_setfacl(info);
- GOTO(out, rc);
- }
-
if (strncmp(xattr_name, trust_string, sizeof(trust_string) - 1) == 0) {
if (strcmp(xattr_name + 8, XATTR_NAME_LOV) == 0)
GOTO(out, rc = -EACCES);
int flags = 0;
xattr = req_capsule_client_get(pill, &RMF_EADATA);
+ if (valid & OBD_MD_FLRMTLSETFACL) {
+ LASSERT(med->med_rmtclient);
+ xattr_len = mdt_rmtlsetfacl(info, xattr_name,
+ (ext_acl_xattr_header *)xattr,
+ &new_xattr);
+ if (xattr_len < 0)
+ GOTO(out_unlock, rc = xattr_len);
+
+ xattr = (char *)new_xattr;
+ }
+
if (body->flags & XATTR_REPLACE)
flags |= LU_XATTR_REPLACE;
}
EXIT;
out_unlock:
+ if (unlikely(new_xattr != NULL))
+ lustre_posix_acl_xattr_free(new_xattr, xattr_len);
mdt_object_unlock(info, obj, lh, rc);
out:
mdt_exit_ucred(info);
CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n",
cld->cld_logname, later, atomic_read(&cld->cld_refcount),
cld->cld_stopping, rq_state);
-
+
/* Hold lock for rq_state */
spin_lock(&config_list_lock);
cld->cld_lostlock = 1;
#include <obd.h>
#include <obd_class.h>
#include <lprocfs_status.h>
+#include <lustre_param.h>
#include "mgs_internal.h"
#ifdef LPROCFS
return rc;
}
+static void seq_show_srpc_rule(struct seq_file *seq, const char *tgtname,
+ struct sptlrpc_rule_set *rset)
+{
+ struct sptlrpc_rule *r;
+ char dirbuf[10];
+ char flvrbuf[40];
+ char *net;
+ int i;
+
+ for (i = 0; i < rset->srs_nrule; i++) {
+ r = &rset->srs_rules[i];
+
+ if (r->sr_netid == LNET_NIDNET(LNET_NID_ANY))
+ net = "default";
+ else
+ net = libcfs_net2str(r->sr_netid);
+
+ if (r->sr_from == LUSTRE_SP_ANY && r->sr_to == LUSTRE_SP_ANY)
+ dirbuf[0] = '\0';
+ else
+ snprintf(dirbuf, sizeof(dirbuf), ".%s2%s",
+ sptlrpc_part2name(r->sr_from),
+ sptlrpc_part2name(r->sr_to));
+
+ sptlrpc_flavor2name(&r->sr_flvr, flvrbuf, sizeof(flvrbuf));
+ seq_printf(seq, "%s.srpc.flavor.%s%s=%s\n", tgtname,
+ net, dirbuf, flvrbuf);
+ }
+}
+
static int mgs_live_seq_show(struct seq_file *seq, void *v)
{
- struct fs_db *fsdb = seq->private;
+ struct fs_db *fsdb = seq->private;
+ struct mgs_tgt_srpc_conf *srpc_tgt;
int i;
down(&fsdb->fsdb_sem);
if (test_bit(i, fsdb->fsdb_ost_index_map))
seq_printf(seq, "%s-OST%04x\n", fsdb->fsdb_name, i);
+ seq_printf(seq, "\nSecure RPC Config Rules:\n");
+#if 0
+ seq_printf(seq, "%s.%s=%s\n", fsdb->fsdb_name,
+ PARAM_SRPC_UDESC, fsdb->fsdb_srpc_fl_udesc ? "yes" : "no");
+#endif
+ for (srpc_tgt = fsdb->fsdb_srpc_tgt; srpc_tgt;
+ srpc_tgt = srpc_tgt->mtsc_next) {
+ seq_show_srpc_rule(seq, srpc_tgt->mtsc_tgt,
+ &srpc_tgt->mtsc_rset);
+ }
+ seq_show_srpc_rule(seq, fsdb->fsdb_name, &fsdb->fsdb_srpc_gen);
+
up(&fsdb->fsdb_sem);
return 0;
}
exp = class_conn2export(conn);
LASSERT(exp);
+ exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
+
if (data != NULL) {
data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
exp->exp_connect_flags = data->ocd_connect_flags;
struct vfsmount *inmnt,
struct list_head *dentry_list);
+struct mgs_tgt_srpc_conf {
+ struct mgs_tgt_srpc_conf *mtsc_next;
+ char *mtsc_tgt;
+ struct sptlrpc_rule_set mtsc_rset;
+};
+
#define INDEX_MAP_SIZE 8192 /* covers indicies to FFFF */
#define FSDB_LOG_EMPTY 0x0001 /* missing client log */
#define FSDB_OLDLOG14 0x0002 /* log starts in old (1.4) style */
/* end COMPAT_146 */
__u32 fsdb_flags;
__u32 fsdb_gen;
+
+ /* in-memory copy of the srpc rules, guarded by fsdb_sem */
+ struct sptlrpc_rule_set fsdb_srpc_gen;
+ struct mgs_tgt_srpc_conf *fsdb_srpc_tgt;
+ unsigned int fsdb_srpc_fl_udesc:1;
};
int mgs_init_fsdb_list(struct obd_device *obd);
#include <lustre_sec.h>
#include "mgs_internal.h"
+static int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
+ struct fs_db *fsdb);
+static int mgs_get_srpc_conf_log(struct fs_db *fsdb, const char *tgt,
+ enum lustre_sec_part from,
+ enum lustre_sec_part to,
+ struct sptlrpc_conf_log *log);
+
/********************** Class functions ********************/
/* Caller must list_del and OBD_FREE each dentry from the list */
RETURN(rc);
}
+static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
+{
+ struct mgs_tgt_srpc_conf *tgtconf;
+
+ /* free target-specific rules */
+ while (fsdb->fsdb_srpc_tgt) {
+ tgtconf = fsdb->fsdb_srpc_tgt;
+ fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
+
+ LASSERT(tgtconf->mtsc_tgt);
+
+ sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
+ OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
+ OBD_FREE_PTR(tgtconf);
+ }
+
+ /* free general rules */
+ sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
+}
+
static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
{
struct mgs_obd *mgs = &obd->u.mgs;
if (rc)
GOTO(err, rc);
+ fsdb->fsdb_srpc_fl_udesc = 1;
sema_init(&fsdb->fsdb_sem, 1);
list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
lproc_mgs_add_live(obd, fsdb);
name_destroy(&fsdb->fsdb_mdtlov);
name_destroy(&fsdb->fsdb_mdtlmv);
name_destroy(&fsdb->fsdb_mdc);
+ mgs_free_fsdb_srpc(fsdb);
OBD_FREE_PTR(fsdb);
}
return rc;
}
+ /* populate srpc rules from params llog */
+ rc = mgs_get_fsdb_srpc_from_llog(obd, fsdb);
+ if (rc) {
+ CERROR("Can't get db from params log %d\n", rc);
+ mgs_free_fsdb(obd, fsdb);
+ return rc;
+ }
+
*dbh = fsdb;
return 0;
return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
}
-static inline int record_sec_flavor(struct obd_device *obd,
- struct llog_handle *llh, char *devname,
- struct sec_flavor_config *conf)
+static inline int record_sptlrpc_conf(struct obd_device *obd,
+ struct llog_handle *llh,
+ char *devname,
+ struct sp