return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
PTLRPC_CRED_UPTODATE);
}
+
static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
{
LASSERT(cred);
LASSERT(cred->pc_ops->refresh);
return cred->pc_ops->refresh(cred);
}
-static inline void ptlrpcs_cred_die(struct ptlrpc_cred *cred)
+
+/* we set the cred flags is safe since cred cache code don't
+ * touch cred with refcount > 0
+ */
+static inline void ptlrpcs_cred_expire(struct ptlrpc_cred *cred)
{
LASSERT(atomic_read(&cred->pc_refcount));
LASSERT(cred->pc_sec);
- if (!(cred->pc_flags & PTLRPC_CRED_DEAD)) {
- spin_lock(&cred->pc_sec->ps_lock);
- cred->pc_flags |= PTLRPC_CRED_DEAD;
- cred->pc_flags &= ~PTLRPC_CRED_UPTODATE;
- list_del_init(&cred->pc_hash);
- spin_unlock(&cred->pc_sec->ps_lock);
- }
+
+ if (cred->pc_flags & PTLRPC_CRED_DEAD)
+ return;
+ cred->pc_flags |= PTLRPC_CRED_DEAD;
+ cred->pc_flags &= ~PTLRPC_CRED_UPTODATE;
+ CWARN("cred %p: get expired\n", cred);
}
-static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
+
+/* usually called upon an UPTODATE cred */
+static inline int ptlrpcs_cred_check_expire(struct ptlrpc_cred *cred)
{
- return(cred->pc_flags & PTLRPC_CRED_DEAD);
+ LASSERT(atomic_read(&cred->pc_refcount));
+ if (cred->pc_expire == 0)
+ return 0;
+ if (time_after(cred->pc_expire, get_seconds()))
+ return 0;
+ ptlrpcs_cred_expire(cred);
+ return 1;
}
static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec,
void ptlrpcs_req_drop_cred(struct ptlrpc_request *req);
int ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req);
int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req);
+int ptlrpcs_check_cred(struct obd_import *imp);
/* internal helpers */
int sec_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
struct inode_operations sm_dir_iops;
struct inode_operations sm_file_iops;
struct inode_operations sm_sym_iops;
+ struct inode_operations sm_special_iops;
struct file_operations sm_dir_fops;
struct file_operations sm_file_fops;
struct file_operations sm_sym_fops;
#include <linux/lustre_mds.h>
#include <linux/lustre_lite.h>
#include <linux/lustre_dlm.h>
+#include <linux/lustre_sec.h>
#include "llite_internal.h"
typedef struct ext2_dir_entry_2 ext2_dirent;
CERROR("lock enqueue: rc: %d\n", rc);
return ERR_PTR(rc);
}
+ } else {
+ if (ptlrpcs_check_cred(obddev->u.cli.cl_import)) {
+ /* return immediately if no credential held */
+ ldlm_lock_decref(&lockh, LCK_PR);
+ return ERR_PTR(-EACCES);
+ }
}
ldlm_lock_dump_handle(D_OTHER, &lockh);
#include <linux/obd_class.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_dlm.h>
+#include <linux/lustre_sec.h>
#include <linux/lprocfs_status.h>
#include <linux/lustre_acl.h>
#include <linux/lustre_lite.h>
&lockh);
}
if (rc) {
+ if (ptlrpcs_check_cred(exp->exp_obd->u.cli.cl_import)) {
+ /* return immediately if no credential held */
+ ldlm_lock_decref(&lockh, mode);
+ RETURN(-EACCES);
+ }
memcpy(&LUSTRE_IT(it)->it_lock_handle, &lockh,
sizeof(lockh));
LUSTRE_IT(it)->it_lock_mode = mode;
rc = ldlm_lock_match(obd->obd_namespace, 0, &res_id, type, policy, mode,
lockh);
if (rc == 1) {
+ if (ptlrpcs_check_cred(obd->u.cli.cl_import)) {
+ /* return immediately if no credential held */
+ ldlm_lock_decref(lockh, mode);
+ RETURN(-EACCES);
+ }
+
osc_set_data_with_check(lockh, data);
if (*flags & LDLM_FL_HAS_INTENT) {
/* I would like to be able to ASSERT here that rss <=
rc = ldlm_lock_match(obd->obd_namespace, 0, &res_id, type,
policy, LCK_PW, lockh);
if (rc == 1) {
+ if (ptlrpcs_check_cred(obd->u.cli.cl_import)) {
+ /* return immediately if no credential held */
+ ldlm_lock_decref(lockh, LCK_PW);
+ RETURN(-EACCES);
+ }
+
/* FIXME: This is not incredibly elegant, but it might
* be more elegant than adding another parameter to
* lock_match. I want a second opinion. */
goto out;
if (signal_pending(current)) {
- CERROR("cred %p: interrupted upcall\n", cred);
+ CERROR("%s: cred %p: interrupted upcall\n",
+ current->comm, cred);
cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR;
res = -EINTR;
} else if (res == 0) {
req->rq_reqbuf, lmsg.data, lmsg.len, mic.data, mic.len);
major = kgss_get_mic(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, &lmsg, &mic);
if (major) {
- CERROR("gss compute mic error, major %x\n", major);
+ CERROR("cred %p: req %p compute mic error, major %x\n",
+ cred, req, major);
rc = -EACCES;
goto out;
}
major = kgss_verify_mic(ctx->gc_gss_ctx, &lmsg, &mic, NULL);
if (major != GSS_S_COMPLETE) {
- CERROR("gss verify mic error: major %x\n", major);
- GOTO(proc_data_out, rc = -EINVAL);
+ CERROR("cred %p: req %p verify mic error: major %x\n",
+ cred, req, major);
+
+ if (major == GSS_S_CREDENTIALS_EXPIRED ||
+ major == GSS_S_CONTEXT_EXPIRED) {
+ ptlrpcs_cred_expire(cred);
+ req->rq_ptlrpcs_restart = 1;
+ rc = 0;
+ } else
+ rc = -EINVAL;
+
+ GOTO(proc_data_out, rc);
}
req->rq_repmsg = (struct lustre_msg *) lmsg.data;
req, cred, (major == GSS_S_NO_CONTEXT) ?
"NO_CONTEXT" : "BAD_SIG");
- ptlrpcs_cred_die(cred);
- rc = ptlrpcs_req_replace_dead_cred(req);
- if (!rc)
- req->rq_ptlrpcs_restart = 1;
- else
- CERROR("replace dead cred failed %d\n", rc);
+ ptlrpcs_cred_expire(cred);
+ req->rq_ptlrpcs_restart = 1;
+ rc = 0;
} else {
CERROR("req %p: unrecognized gss error (%x/%x)\n",
req, major, minor);
vlen -= 4;
msg_buf.buf = (__u8 *) req->rq_reqmsg - GSS_PRIVBUF_PREFIX_LEN;
- msg_buf.buflen = req->rq_reqlen + GSS_PRIVBUF_PREFIX_LEN + GSS_PRIVBUF_SUFFIX_LEN;
+ msg_buf.buflen = req->rq_reqlen + GSS_PRIVBUF_PREFIX_LEN +
+ GSS_PRIVBUF_SUFFIX_LEN;
msg_buf.dataoff = GSS_PRIVBUF_PREFIX_LEN;
msg_buf.datalen = req->rq_reqlen;
major = kgss_wrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT,
&msg_buf, &cipher_buf);
if (major) {
- CERROR("error wrap: major 0x%x\n", major);
+ CERROR("cred %p: error wrap: major 0x%x\n", cred, major);
GOTO(out, rc = -EINVAL);
}
struct ptlrpcs_wire_hdr *sec_hdr;
rawobj_t cipher_text, plain_text;
__u32 *vp, vlen, subflavor, proc, seq, svc;
- int rc;
+ __u32 major, rc;
ENTRY;
LASSERT(req->rq_repbuf);
ctx = gss_cred_get_ctx(cred);
LASSERT(ctx);
- rc = kgss_unwrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT,
- &cipher_text, &plain_text);
- if (rc) {
- CERROR("error unwrap: 0x%x\n", rc);
- GOTO(proc_out, rc = -EINVAL);
+ major = kgss_unwrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT,
+ &cipher_text, &plain_text);
+ if (major) {
+ CERROR("cred %p: error unwrap: major 0x%x\n",
+ cred, major);
+
+ if (major == GSS_S_CREDENTIALS_EXPIRED ||
+ major == GSS_S_CONTEXT_EXPIRED) {
+ ptlrpcs_cred_expire(cred);
+ req->rq_ptlrpcs_restart = 1;
+ rc = 0;
+ } else
+ rc = -EINVAL;
+
+ GOTO(proc_out, rc);
}
req->rq_repmsg = (struct lustre_msg *) vp;
{
LASSERT(cred->pc_sec);
+ /* only unlink non-busy entries */
if (atomic_read(&cred->pc_refcount) != 0)
return 0;
+ /* expire is 0 means never expire. a newly created gss cred
+ * which during upcall also has 0 expiration
+ */
+ if (cred->pc_expire == 0)
+ return 0;
+ /* check real expiration */
if (time_after(cred->pc_expire, get_seconds()))
return 0;
+ LASSERT((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
+ PTLRPC_CRED_UPTODATE);
+ CWARN("cred %p: get expired, unlink\n", cred);
+
list_del(&cred->pc_hash);
list_add(&cred->pc_hash, freelist);
- CDEBUG(D_SEC, "put cred %p into freelist\n", cred);
return 1;
}
for (i = 0; i < PTLRPC_CREDCACHE_NR; i++) {
list_for_each_entry_safe(cred, n, &sec->ps_credcache[i],
pc_hash) {
+ if (cred->pc_flags & (PTLRPC_CRED_DEAD |
+ PTLRPC_CRED_ERROR)) {
+ LASSERT(atomic_read(&cred->pc_refcount));
+ continue;
+ }
ptlrpcs_cred_unlink_expired(cred, freelist);
}
}
ptlrpcs_credcache_gc(sec, &freelist);
list_for_each_entry_safe(cred, n, &sec->ps_credcache[hash], pc_hash) {
- if (cred->pc_flags & PTLRPC_CRED_DEAD)
+ /* for DEAD and ERROR entries, its final put will
+ * release them, so we simply skip here.
+ */
+ if (cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) {
+ LASSERT(atomic_read(&cred->pc_refcount));
continue;
+ }
if (ptlrpcs_cred_unlink_expired(cred, &freelist))
continue;
if (cred->pc_ops->match(cred, vcred)) {
RETURN(cred);
}
-int ptlrpcs_req_get_cred(struct ptlrpc_request *req)
+static struct ptlrpc_cred *get_cred(struct ptlrpc_sec *sec)
{
- struct obd_import *imp = req->rq_import;
struct vfs_cred vcred;
- ENTRY;
-
- LASSERT(!req->rq_cred);
- LASSERT(imp);
- LASSERT(imp->imp_sec);
+ LASSERT(sec);
/* XXX
* for now we simply let PAG == real uid
*/
vcred.vc_pag = (__u64) current->uid;
vcred.vc_uid = current->uid;
- req->rq_cred = cred_cache_lookup(imp->imp_sec, &vcred, 1);
+ return cred_cache_lookup(sec, &vcred, 1);
+}
+
+int ptlrpcs_req_get_cred(struct ptlrpc_request *req)
+{
+ struct obd_import *imp = req->rq_import;
+ ENTRY;
+
+ LASSERT(!req->rq_cred);
+ LASSERT(imp);
+
+ req->rq_cred = get_cred(imp->imp_sec);
if (!req->rq_cred) {
CERROR("req %p: fail to get cred from cache\n", req);
RETURN(0);
}
+/*
+ * check whether current user have valid credential for an import or not.
+ * might repeatedly try in case of non-fatal errors.
+ * return 0 on success, 1 on failure
+ */
+int ptlrpcs_check_cred(struct obd_import *imp)
+{
+ struct ptlrpc_cred *cred;
+ ENTRY;
+
+again:
+ cred = get_cred(imp->imp_sec);
+ if (!cred)
+ RETURN(0);
+
+ if (ptlrpcs_cred_is_uptodate(cred)) {
+ if (!ptlrpcs_cred_check_expire(cred)) {
+ ptlrpcs_cred_put(cred, 1);
+ RETURN(0);
+ } else {
+ ptlrpcs_cred_put(cred, 1);
+ goto again;
+ }
+ }
+
+ ptlrpcs_cred_refresh(cred);
+ if (ptlrpcs_cred_is_uptodate(cred)) {
+ ptlrpcs_cred_put(cred, 1);
+ RETURN(0);
+ }
+
+ if (cred->pc_flags & PTLRPC_CRED_ERROR ||
+ !imp->imp_replayable) {
+ ptlrpcs_cred_put(cred, 1);
+ RETURN(1);
+ }
+
+ ptlrpcs_cred_put(cred, 1);
+
+ if (signal_pending(current)) {
+ CWARN("%s: interrupted\n", current->comm);
+ RETURN(1);
+ }
+ goto again;
+}
+
static void ptlrpcs_sec_destroy(struct ptlrpc_sec *sec);
void ptlrpcs_cred_put(struct ptlrpc_cred *cred, int sync)
LASSERT(atomic_read(&cred->pc_refcount));
spin_lock(&sec->ps_lock);
- if (atomic_dec_and_test(&cred->pc_refcount) &&
- sync && cred->pc_flags & PTLRPC_CRED_DEAD) {
+ if (atomic_dec_and_test(&cred->pc_refcount) && sync &&
+ cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) {
list_del_init(&cred->pc_hash);
ptlrpcs_cred_destroy(cred);
if (!atomic_read(&sec->ps_credcount) &&
LASSERT(cred);
- if (ptlrpcs_cred_is_uptodate(cred))
- RETURN(0);
+ if (ptlrpcs_cred_is_uptodate(cred)) {
+ if (!ptlrpcs_cred_check_expire(cred))
+ RETURN(0);
+ }
if (cred->pc_flags & PTLRPC_CRED_ERROR) {
req->rq_ptlrpcs_err = 1;
LASSERT(cred == req->rq_cred);
CERROR("req %p: failed to replace dead cred %p\n",
req, cred);
+ req->rq_ptlrpcs_err = 1;
RETURN(-ENOMEM);
}
}
EXPORT_SYMBOL(ptlrpcs_req_drop_cred);
EXPORT_SYMBOL(ptlrpcs_req_replace_dead_cred);
EXPORT_SYMBOL(ptlrpcs_req_refresh_cred);
+EXPORT_SYMBOL(ptlrpcs_check_cred);
EXPORT_SYMBOL(ptlrpcs_cli_alloc_reqbuf);
EXPORT_SYMBOL(ptlrpcs_cli_free_reqbuf);
EXPORT_SYMBOL(ptlrpcs_cli_alloc_repbuf);
unlock_kernel();
}
+static void setup_sm_special_ops(struct inode *inode)
+{
+ struct smfs_super_info *smb = S2SMI(inode->i_sb);
+ struct inode *cache_inode = I2CI(inode);
+
+ setup_iops(cache_inode, &smfs_special_iops, &smb->sm_ops->sm_special_iops);
+
+ lock_kernel();
+ smb->smsi_ops_check |= SPECIAL_OPS_CHECK;
+ unlock_kernel();
+}
+
#define SMFS_IOPEN_INO 1
void sm_set_inode_ops(struct inode *inode)
setup_sm_symlink_ops(inode);
inode->i_op = &smb->sm_ops->sm_sym_iops;
inode->i_fop = &smb->sm_ops->sm_sym_fops;
+ } else {
+ if (!(smb->smsi_ops_check & SPECIAL_OPS_CHECK))
+ setup_sm_special_ops(inode);
+ inode->i_op = &smb->sm_ops->sm_special_iops;
}
}
}
struct inode_operations smfs_dir_iops = {
- create: smfs_create,
- lookup: smfs_lookup,
+ .create = smfs_create,
+ .lookup = smfs_lookup,
#if HAVE_LOOKUP_RAW
- lookup_raw: smfs_lookup_raw,
+ .lookup_raw = smfs_lookup_raw,
#endif
- link: smfs_link, /* BKL held */
- unlink: smfs_unlink, /* BKL held */
- symlink: smfs_symlink, /* BKL held */
- mkdir: smfs_mkdir, /* BKL held */
- rmdir: smfs_rmdir, /* BKL held */
- mknod: smfs_mknod, /* BKL held */
- rename: smfs_rename, /* BKL held */
- setxattr: smfs_setxattr, /* BKL held */
- getxattr: smfs_getxattr, /* BKL held */
- listxattr: smfs_listxattr, /* BKL held */
- removexattr: smfs_removexattr, /* BKL held */
+ .link = smfs_link, /* BKL held */
+ .unlink = smfs_unlink, /* BKL held */
+ .symlink = smfs_symlink, /* BKL held */
+ .mkdir = smfs_mkdir, /* BKL held */
+ .rmdir = smfs_rmdir, /* BKL held */
+ .mknod = smfs_mknod, /* BKL held */
+ .rename = smfs_rename, /* BKL held */
+ .setxattr = smfs_setxattr,
+ .getxattr = smfs_getxattr,
+ .listxattr = smfs_listxattr,
+ .removexattr = smfs_removexattr,
+ .permission = smfs_permission,
};
struct inode_operations smfs_iopen_iops = {
- lookup: smfs_iopen_lookup,
+ .lookup = smfs_iopen_lookup,
};
static ssize_t smfs_read_dir(struct file *filp, char *buf,
RETURN(rc);
}
+int smfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+ struct inode *cache_inode = I2CI(inode);
+ int rc = 0;
+
+ ENTRY;
+
+ LASSERT(cache_inode);
+ LASSERT(cache_inode->i_op->permission);
+
+ pre_smfs_inode(inode, cache_inode);
+
+ rc = cache_inode->i_op->permission(cache_inode, mask, nd);
+
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
struct inode_operations smfs_file_iops = {
.truncate = smfs_truncate, /* BKL held */
.setattr = smfs_setattr, /* BKL held */
- .setxattr = smfs_setxattr, /* BKL held */
- .getxattr = smfs_getxattr, /* BKL held */
- .listxattr = smfs_listxattr, /* BKL held */
- .removexattr = smfs_removexattr, /* BKL held */
+ .setxattr = smfs_setxattr,
+ .getxattr = smfs_getxattr,
+ .listxattr = smfs_listxattr,
+ .removexattr = smfs_removexattr,
+ .permission = smfs_permission,
+};
+
+struct inode_operations smfs_special_iops = {
+ .setattr = smfs_setattr, /* BKL held */
+ .setxattr = smfs_setxattr,
+ .getxattr = smfs_getxattr,
+ .listxattr = smfs_listxattr,
+ .removexattr = smfs_removexattr,
+ .permission = smfs_permission,
};
#define INODE_OPS_CHECK 0x2
#define FILE_OPS_CHECK 0x4
#define DENTRY_OPS_CHECK 0x8
-#define DEV_OPS_CHECK 0x10
+#define SPECIAL_OPS_CHECK 0x10
#define SYMLINK_OPS_CHECK 0x20
#define DIR_OPS_CHECK 0x40
/*file.c*/
extern struct inode_operations smfs_file_iops;
extern struct file_operations smfs_file_fops;
+extern struct inode_operations smfs_special_iops;
extern int smfs_ioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg);
extern int smfs_fsync(struct file * file, struct dentry *dentry, int datasync);
size_t size);
extern ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
extern int smfs_removexattr(struct dentry *dentry, const char *name);
+extern int smfs_permission(struct inode *inode, int mask, struct nameidata *nd);
extern int smfs_open(struct inode * inode, struct file * filp);
extern int smfs_release(struct inode * inode, struct file * filp);
/*inode.c*/
struct inode_operations smfs_sym_iops = {
.readlink = smfs_readlink,
.follow_link = smfs_follow_link,
- .setxattr = smfs_setxattr, /* BKL held */
- .getxattr = smfs_getxattr, /* BKL held */
- .listxattr = smfs_listxattr, /* BKL held */
- .removexattr = smfs_removexattr, /* BKL held */
+ .setxattr = smfs_setxattr,
+ .getxattr = smfs_getxattr,
+ .listxattr = smfs_listxattr,
+ .removexattr = smfs_removexattr,
+ .permission = smfs_permission,
};
struct file_operations smfs_sym_fops = {
--- /dev/null
+ACL inheritance test. Run these tests on a filesystem with ACL support.
+
+
+ $ id -u
+ > 0
+
+ $ mkdir d
+ $ setfacl -d -m group:bin:r-x d
+ $ getfacl d
+ > # file: d
+ > # owner: root
+ > # group: root
+ > user::rwx
+ > group::r-x
+ > other::r-x
+ > default:user::rwx
+ > default:group::r-x
+ > default:group:bin:r-x
+ > default:mask::r-x
+ > default:other::r-x
+ >
+
+ $ mkdir d/subdir
+ $ getfacl d/subdir
+ > # file: d/subdir
+ > # owner: root
+ > # group: root
+ > user::rwx
+ > group::r-x
+ > group:bin:r-x
+ > mask::r-x
+ > other::r-x
+ > default:user::rwx
+ > default:group::r-x
+ > default:group:bin:r-x
+ > default:mask::r-x
+ > default:other::r-x
+ >
+
+ $ touch d/f
+ $ ls -l d/f | awk -- '{ print $1 }'
+ > -rw-r--r--+
+ $ getfacl d/f
+ > # file: d/f
+ > # owner: root
+ > # group: root
+ > user::rw-
+ > group::r-x #effective:r--
+ > group:bin:r-x #effective:r--
+ > mask::r--
+ > other::r--
+ >
+
+ $ su bin
+ $ echo i >> d/f
+ > d/f: Permission denied
+
+Changed by CFS: (1). reduce the tree level to 2 (for shortening
+time of local tests). (2). add one more getfacl test since dir
+might be distributed around MDS's.
+
+ $ su
+ $ rm d/f
+ $ rmdir d/subdir
+ $ mv d tree
+ $ ./make-tree
+ $ getfacl tree/dir0/dir5/file4
+ > # file: tree/dir0/dir5/file4
+ > # owner: root
+ > # group: root
+ > user::rw-
+ > group::r-x #effective:r--
+ > group:bin:r-x #effective:r--
+ > mask::r--
+ > other::r--
+ >
+ $ getfacl tree/dir0/dir6/file4
+ > # file: tree/dir0/dir6/file4
+ > # owner: root
+ > # group: root
+ > user::rw-
+ > group::r-x #effective:r--
+ > group:bin:r-x #effective:r--
+ > mask::r--
+ > other::r--
+ >
+ $ echo i >> tree/dir6/dir2/file2
+ $ echo i > tree/dir1/f
+ $ ls -l tree/dir1/f | awk -- '{ print $1 }'
+ > -rw-r--r--+
+ $ su bin
+ $ echo i > tree/dir6/dir2/f
+ > tree/dir6/dir2/f: No such file or directory
+ $ su
+
+ $ rm -rf tree
+
+
+Original scripts, comment out by CFS.
+#
+# $ su
+# $ rm d/f
+# $ rmdir d/subdir
+# $ mv d tree
+# $ ./make-tree
+# $ getfacl tree/dir0/dir5/dir7/file4
+# > # file: tree/dir0/dir5/dir7/file4
+# > # owner: root
+# > # group: root
+# > user::rw-
+# > group::r-x #effective:r--
+# > group:bin:r-x #effective:r--
+# > mask::r--
+# > other::r--
+# >
+# $ echo i >> tree/dir6/dir2/dir1/file2
+# $ echo i > tree/dir1/f
+# $ ls -l tree/dir1/f | awk -- '{ print $1 }'
+# > -rw-r--r--+
+# $ su bin
+# $ echo i > tree/dir6/dir2/f
+# > tree/dir6/dir2/f: No such file or directory
+# $ su
+#
+# $ rm -rf tree
+
+
+
+
--- /dev/null
+#!/bin/sh
+
+# reduce LEVELS from 3 => 2 by CFS
+LEVELS=2 ; [ -z "$1" ] || LEVELS=$1
+DIRS=10 ; [ -z "$2" ] || DIRS=$2
+FILES=10 ; [ -z "$2" ] || FILES=$3
+NUMBER_OF_ACLS=50 ; [ -z "$3" ] || NUMBER_OF_ACLS=$4
+
+function random_dir() {
+ mkdir -p $1
+ #setfacl -s "u::rwx,u:$[($RANDOM % $NUMBER_OF_ACLS)+1000]:rwx,g::rx,o:-" $1
+}
+
+function random_file() {
+ touch $1
+ #setfacl -s "u::rw,u:$[($RANDOM % $NUMBER_OF_ACLS)+1000]:rw,g::r,o:-" $1
+}
+
+function create () {
+ local LEVEL=$1
+ if [ $LEVEL -eq 0 ]; then
+ local I=0
+ while [ $I -lt $FILES ]; do
+ random_file file$I
+ I=$[$I+1]
+ done
+ else
+ local I=0
+ while [ $I -lt $DIRS ]; do
+ random_dir dir$I
+ cd dir$I
+ create $[$LEVEL-1]
+ cd ..
+ I=$[$I+1]
+ done
+ fi
+ return
+}
+
+mkdir -p tree
+cd tree
+create $LEVELS
+cd ..
+exit 0
+
$ su bin
$ echo e/*
> e/h
- $ echo i > e/i
- > e/i: Permission denied
+following 2 lines seems not valid, which also failed on ext3 in FC3 enviroment,
+although it pass in FC2. commented out by CFS (agreed with HP)
+# $ echo i > e/i
+# > e/i: Permission denied
$ su
$ setfacl -m u:bin:rwx e
TMP=${TMP:-/tmp}
FSTYPE=${FSTYPE:-ext3}
+NETTYPE=${NETTYPE:-tcp}
CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
CREATETEST=${CREATETEST:-createtest}
SOCKETCLIENT=${SOCKETCLIENT:-socketclient}
IOPENTEST1=${IOPENTEST1:-iopentest1}
IOPENTEST2=${IOPENTEST2:-iopentest2}
+RUNAS=${RUNAS:-"runas"}
. krb5_env.sh
if [ $UID -ne 0 ]; then
- RUNAS_ID="$UID"
- RUNAS=""
-else
- RUNAS_ID=${RUNAS_ID:-500}
- RUNAS=${RUNAS:-"runas -u $RUNAS_ID"}
-fi
-
-if [ `using_krb5_sec $SECURITY` == 'y' ] ; then
- start_krb5_kdc || exit 1
- if [ $RUNAS_ID -ne $UID ]; then
- $RUNAS ./krb5_refresh_cache.sh || exit 2
- fi
+ echo "Must be run as root"
+ exit 1
fi
export NAME=${NAME:-local}
mynidstr(){
lctl << EOF
- network tcp
- mynid
+ network $NETTYPE
+ shownid
quit
EOF
}
test_1(){
mdsnum=`mdsdevice|awk ' $3=="mds" {print $1}'`
if [ ! -z "$mdsnum" ];then
- mynid=`mynidstr|awk '{print $4}'`
+ mynid=`mynidstr`
mkdir $DIR/test_0a_dir1
touch $DIR/test_0a_file1
ln -s $DIR/test_0a_file1 $DIR/test_0a_filelink1
}
test_3 () {
- SAVE_UMASK=`umask`
- cd $DIR
+ # acl tests are using user "bin" and "daemon", which uid are 1 and 2
+ # in most distributions
+ if [ `using_krb5_sec $SECURITY` == 'y' ] ; then
+ $RUNAS -u 1 ./krb5_refresh_cache.sh || exit 20
+ $RUNAS -u 2 ./krb5_refresh_cache.sh || exit 21
+ fi
+
+ SAVE_UMASK=`umask`
+ cd $DIR
+
+ run_acl_subtest cp || return 1
+ run_acl_subtest getfacl-noacl || return 2
+ run_acl_subtest misc || return 3
+ run_acl_subtest permissions || return 4
+ run_acl_subtest setfacl || return 5
- run_acl_subtest cp || return 1
- run_acl_subtest getfacl-noacl || return 2
- run_acl_subtest misc || return 3
- run_acl_subtest permissions || return 4
- run_acl_subtest setfacl || return 5
+ # inheritance test got from HP
+ cp $SAVE_PWD/acl/make-tree . || return 6
+ chmod +x make-tree || return 7
+ run_acl_subtest inheritance || return 8
+ rm -f make-tree
- cd $SAVED_PWD
- umask $SAVE_UMASK
+ cd $SAVED_PWD
+ umask $SAVE_UMASK
}
run_test 3 "==============acl test ============="