ocfs2: add security EA and ACL support V5
Subsystems (3)
cover ocfs2: add security EA and ACL support V5
Hi, all
This the 5th version for add security EA and acl support in ocfs2. In this round I fixed many problem as Mark commented. Them based on Mark's merge_window branch.
The top 4 patches are for security EA.
1. move new inode allocation from transaction
This patch actually is from Jan's patch
http://oss.oracle.com/pipermail/ocfs2-devel/2008-October/003266.html
2. ocfs2_xattr_set_handle
I remove the extend_trans from this function as we have reserve credits with start trans.
3. add security xattr API
4. add ocfs2_init_security in mknod
calculate credits for security xattr before start trans.
add setting security attribute on symlinks.
The next 6 patches are for acl.
5. add ocfs2_xattr_get_nolock
6. add posix acl api
combine ocfs2_acl_set_handle and ocfs2_acl_set into one function.
7. add ocfs2_check_acl
8. add ocfs2_acl_chmod
move acl_chmod out of the transaction in ocfs2_setattr.
9. add ocfs2_init_acl in mknod
calculate credits for acl xattrs before start trans.
10. add mount and Kconfig options for acl
PATCH 1/10 ocfs2: move new inode allocation out of the transaction
Move out inode allocation from ocfs2_mknod_locked() because vfs_dq_init() must be called outside of a transaction.
--- fs/ocfs2/namei.c | 108 ++++++++++++++++++++++++++++++++---------------------- 1 files changed, 64 insertions(+), 44 deletions(-)
fs/ocfs2/namei.c +64 -44
@@ -66,12 +66,12 @@static int ocfs2_mknod_locked (struct ocfs2_super *osb,struct inode *dir, -struct dentry *dentry,int mode, +struct inode *inode, +struct dentry *dentry,dev_t dev,struct buffer_head **new_fe_bh,struct buffer_head *parent_fe_bh,handle_t *handle, -struct inode **ret_inode,struct ocfs2_alloc_context *inode_ac); static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
@@ -186,6 +186,34 @@ bail:return ret; } +static struct inode *ocfs2_get_init_inode (struct inode *dir,int mode) +{ +struct inode *inode; + + inode =new_inode (dir->i_sb); +if (!inode) { +mlog (ML_ERROR ,"new_inode failed!\n" ); +return NULL ; + } + +/* populate as many fields early on as possible - many of +* these are used by the support functions here and in +* callers. */ +if (S_ISDIR (mode)) + inode->i_nlink =2 ; +else + inode->i_nlink =1 ; + inode->i_uid = current->fsuid; +if (dir->i_mode &S_ISGID ) { + inode->i_gid = dir->i_gid; +if (S_ISDIR (mode)) + mode |=S_ISGID ; + }else + inode->i_gid = current->fsgid; + inode->i_mode = mode; +return inode; +} + static int ocfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
@@ -250,6 +278,13 @@ static int ocfs2_mknod(struct inode *dir, goto leave; } + inode =ocfs2_get_init_inode (dir, mode); +if (!inode) { + status = -ENOMEM ; +mlog_errno (status); + goto leave; + } +/* Reserve a cluster if creating an extent based directory. */ if (S_ISDIR (mode) && !ocfs2_supports_inline_data (osb)) { status =ocfs2_reserve_clusters (osb,1 , &data_ac);
@@ -269,9 +304,9 @@ static int ocfs2_mknod(struct inode *dir, }/* do the real work now. */ - status =ocfs2_mknod_locked (osb, dir, dentry, mode, dev, + status =ocfs2_mknod_locked (osb, dir, inode, dentry, dev, &new_fe_bh, parent_fe_bh, handle, - &inode, inode_ac); + inode_ac);if (status <0 ) {mlog_errno (status); goto leave;
@@ -332,8 +367,10 @@ leave:brelse (de_bh);brelse (parent_fe_bh); -if ((status <0 ) && inode) +if ((status <0 ) && inode) { +clear_nlink (inode);iput (inode); + }if (inode_ac)ocfs2_free_alloc_context (inode_ac);
@@ -348,12 +385,12 @@ leave:static int ocfs2_mknod_locked (struct ocfs2_super *osb,struct inode *dir, -struct dentry *dentry,int mode, +struct inode *inode, +struct dentry *dentry,dev_t dev,struct buffer_head **new_fe_bh,struct buffer_head *parent_fe_bh,handle_t *handle, -struct inode **ret_inode,struct ocfs2_alloc_context *inode_ac) {int status =0 ;
@@ -361,14 +398,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,struct ocfs2_extent_list *fel;u64 fe_blkno =0 ;u16 suballoc_bit; -struct inode *inode =NULL ; -mlog_entry ("(0x%p, 0x%p, %d, %lu, '%.*s')\n" , dir, dentry, mode, - (unsigned long )dev, dentry->d_name.len, +mlog_entry ("(0x%p, 0x%p, %d, %lu, '%.*s')\n" , dir, dentry, + inode->i_mode, (unsigned long )dev, dentry->d_name.len, dentry->d_name.name); *new_fe_bh =NULL ; - *ret_inode =NULL ; status =ocfs2_claim_new_inode (osb, handle, inode_ac, &suballoc_bit, &fe_blkno);
@@ -377,23 +412,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, goto leave; } - inode =new_inode (dir->i_sb); -if (!inode) { - status = -ENOMEM ; -mlog (ML_ERROR ,"new_inode failed!\n" ); - goto leave; - } -/* populate as many fields early on as possible - many of * these are used by the support functions here and in * callers. */ inode->i_ino =ino_from_blkno (osb->sb, fe_blkno);OCFS2_I (inode)->ip_blkno = fe_blkno; -if (S_ISDIR (mode)) - inode->i_nlink =2 ; -else - inode->i_nlink =1 ; - inode->i_mode = mode;spin_lock (&osb->osb_lock); inode->i_generation = osb->s_next_generation++;spin_unlock (&osb->osb_lock);
@@ -421,17 +444,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, fe->i_blkno =cpu_to_le64 (fe_blkno); fe->i_suballoc_bit =cpu_to_le16 (suballoc_bit); fe->i_suballoc_slot =cpu_to_le16 (inode_ac->ac_alloc_slot); - fe->i_uid =cpu_to_le32 (current->fsuid); -if (dir->i_mode &S_ISGID ) { - fe->i_gid =cpu_to_le32 (dir->i_gid); -if (S_ISDIR (mode)) - mode |=S_ISGID ; - }else - fe->i_gid =cpu_to_le32 (current->fsgid); - fe->i_mode =cpu_to_le16 (mode); -if (S_ISCHR (mode) ||S_ISBLK (mode)) + fe->i_uid =cpu_to_le32 (inode->i_uid); + fe->i_gid =cpu_to_le32 (inode->i_gid); + fe->i_mode =cpu_to_le16 (inode->i_mode); +if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode)) fe->id1.dev1.i_rdev =cpu_to_le64 (huge_encode_dev (dev)); - fe->i_links_count =cpu_to_le16 (inode->i_nlink); fe->i_last_eb_blk =0 ;
@@ -446,7 +463,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,/* * If supported, directories start with inline data. */ -if (S_ISDIR (mode) &&ocfs2_supports_inline_data (osb)) { +if (S_ISDIR (inode->i_mode) &&ocfs2_supports_inline_data (osb)) {u16 feat =le16_to_cpu (fe->i_dyn_features); fe->i_dyn_features =cpu_to_le16 (feat |OCFS2_INLINE_DATA_FL );
@@ -484,17 +501,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, status =0 ;/* error in ocfs2_create_new_inode_locks is not * critical */ - *ret_inode = inode; leave:if (status <0 ) {if (*new_fe_bh) {brelse (*new_fe_bh); *new_fe_bh =NULL ; } -if (inode) { -clear_nlink (inode); -iput (inode); - } }mlog_exit (status);
@@ -1542,6 +1554,13 @@ static int ocfs2_symlink(struct inode *dir, goto bail; } + inode =ocfs2_get_init_inode (dir,S_IFLNK |S_IRWXUGO ); +if (!inode) { + status = -ENOMEM ; +mlog_errno (status); + goto bail; + } +/* don't reserve bitmap space for fast symlinks. */ if (l >ocfs2_fast_symlink_chars (sb)) { status =ocfs2_reserve_clusters (osb,1 , &data_ac);
@@ -1560,10 +1579,9 @@ static int ocfs2_symlink(struct inode *dir, goto bail; } - status =ocfs2_mknod_locked (osb, dir, dentry, -S_IFLNK |S_IRWXUGO ,0 , - &new_fe_bh, parent_fe_bh, handle, - &inode, inode_ac); + status =ocfs2_mknod_locked (osb, dir, inode, dentry, +0 , &new_fe_bh, parent_fe_bh, handle, + inode_ac);if (status <0 ) {mlog_errno (status); goto bail;
@@ -1644,8 +1662,10 @@ bail:ocfs2_free_alloc_context (inode_ac);if (data_ac)ocfs2_free_alloc_context (data_ac); -if ((status <0 ) && inode) +if ((status <0 ) && inode) { +clear_nlink (inode);iput (inode); + }mlog_exit (status);
Signature · 1 line
1.5.4.1
PATCH 2/10 ocfs2: add ocfs2_xattr_set_handle
In reply to Tiger YangThis function use to set xattr in a started transaction. It is only called during creating inode for init security/acl xattrs of the new inode. These xattrs could be put into ibody or extent block, so xattr bucket would not
be use in this case. The transanction credits also be reserved in here.
--- fs/ocfs2/xattr.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.h | 4 +++ 2 files changed, 72 insertions(+), 0 deletions(-)
fs/ocfs2/xattr.c +68 -0
@@ -2326,6 +2326,74 @@ out: }/* +* This function only called duing creating inode +* for init security/acl xattrs of the new inode. +* The xattrs could be put into ibody or extent block, +* xattr bucket would not be use in this case. +* transanction credits also be reserved in here. +*/ +int ocfs2_xattr_set_handle (handle_t *handle, +struct inode *inode, +struct buffer_head *di_bh, +int name_index, +const char *name, +const void *value, +size_t value_len, +int flags, +struct ocfs2_alloc_context *meta_ac, +struct ocfs2_alloc_context *data_ac) +{ +struct ocfs2_dinode *di; +int ret; + +struct ocfs2_xattr_info xi = { + .name_index = name_index, + .name = name, + .value = value, + .value_len = value_len, + }; + +struct ocfs2_xattr_search xis = { + .not_found = -ENODATA , + }; + +struct ocfs2_xattr_search xbs = { + .not_found = -ENODATA , + }; + +struct ocfs2_xattr_set_ctxt ctxt = { + .handle = handle, + .meta_ac = meta_ac, + .data_ac = data_ac, + }; + +if (!ocfs2_supports_xattr (OCFS2_SB (inode->i_sb))) +return -EOPNOTSUPP ; + + xis.inode_bh = xbs.inode_bh = di_bh; + di = (struct ocfs2_dinode *)di_bh->b_data; + +down_write (&OCFS2_I (inode)->ip_xattr_sem); + + ret =ocfs2_xattr_ibody_find (inode, name_index, name, &xis); +if (ret) + goto cleanup; +if (xis.not_found) { + ret =ocfs2_xattr_block_find (inode, name_index, name, &xbs); +if (ret) + goto cleanup; + } + + ret =__ocfs2_xattr_set_handle (inode, di, &xi, &xis, &xbs, &ctxt); + +cleanup: +up_write (&OCFS2_I (inode)->ip_xattr_sem); +brelse (xbs.xattr_bh); + +return ret; +} + +/* * ocfs2_xattr_set() * * Set, replace or remove an extended attribute for this inode.
fs/ocfs2/xattr.h +4 -0
@@ -37,6 +37,10 @@ extern struct xattr_handler *ocfs2_xattr_handlers[];ssize_t ocfs2_listxattr (struct dentry *,char *,size_t );int ocfs2_xattr_set (struct inode *,int ,const char *,const void *,size_t ,int ); +int ocfs2_xattr_set_handle (handle_t *,struct inode *,struct buffer_head *, +int ,const char *,const void *,size_t ,int , +struct ocfs2_alloc_context *, +struct ocfs2_alloc_context *);int ocfs2_xattr_remove (struct inode *,struct buffer_head *);#endif /* OCFS2_XATTR_H */
Signature · 1 line
1.5.4.1
PATCH 3/10 ocfs2: add security xattr API
In reply to Tiger YangThis patch add security xattr set/get/list APIs to support security xattr in ocfs2.
--- fs/ocfs2/xattr.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.h | 1 + 2 files changed, 48 insertions(+), 0 deletions(-)
fs/ocfs2/xattr.c +47 -0
@@ -35,6 +35,7 @@#include <linux/init.h> #include <linux/module.h> #include <linux/string.h> +#include <linux/security.h> #define MLOG_MASK_PREFIX ML_XATTR#include <cluster/masklog.h>
@@ -88,12 +89,14 @@ static struct ocfs2_xattr_def_value_root def_xv = {struct xattr_handler *ocfs2_xattr_handlers[] = { &ocfs2_xattr_user_handler, &ocfs2_xattr_trusted_handler, + &ocfs2_xattr_security_handler,NULL };static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX ] = { [OCFS2_XATTR_INDEX_USER ] = &ocfs2_xattr_user_handler, [OCFS2_XATTR_INDEX_TRUSTED ] = &ocfs2_xattr_trusted_handler, + [OCFS2_XATTR_INDEX_SECURITY ] = &ocfs2_xattr_security_handler, };struct ocfs2_xattr_info {
@@ -4983,6 +4986,50 @@ out: }/* +* 'security' attributes support +*/ +static size_t ocfs2_xattr_security_list (struct inode *inode,char *list, +size_t list_size,const char *name, +size_t name_len) +{ +const size_t prefix_len =XATTR_SECURITY_PREFIX_LEN ; +const size_t total_len = prefix_len + name_len +1 ; + +if (list && total_len <= list_size) { +memcpy (list,XATTR_SECURITY_PREFIX , prefix_len); +memcpy (list + prefix_len, name, name_len); + list[prefix_len + name_len] ='\0' ; + } +return total_len; +} + +static int ocfs2_xattr_security_get (struct inode *inode,const char *name, +void *buffer,size_t size) +{ +if (strcmp (name,"" ) ==0 ) +return -EINVAL ; +return ocfs2_xattr_get (inode,OCFS2_XATTR_INDEX_SECURITY , name, + buffer, size); +} + +static int ocfs2_xattr_security_set (struct inode *inode,const char *name, +const void *value,size_t size,int flags) +{ +if (strcmp (name,"" ) ==0 ) +return -EINVAL ; + +return ocfs2_xattr_set (inode,OCFS2_XATTR_INDEX_SECURITY , name, value, + size, flags); +} + +struct xattr_handler ocfs2_xattr_security_handler = { + .prefix =XATTR_SECURITY_PREFIX , + .list = ocfs2_xattr_security_list, + .get = ocfs2_xattr_security_get, + .set = ocfs2_xattr_security_set, +}; + +/* * 'trusted' attributes support */ static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
fs/ocfs2/xattr.h +1 -0
@@ -32,6 +32,7 @@ enum ocfs2_xattr_type {extern struct xattr_handler ocfs2_xattr_user_handler;extern struct xattr_handler ocfs2_xattr_trusted_handler; +extern struct xattr_handler ocfs2_xattr_security_handler;extern struct xattr_handler *ocfs2_xattr_handlers[];ssize_t ocfs2_listxattr (struct dentry *,char *,size_t );
Signature · 1 line
1.5.4.1
PATCH 4/10 ocfs2: add ocfs2_init_security in mknod
In reply to Tiger Yangsecurity xattr must be set when creating a new inode. we do this in three steps. first, get security xattr's name and value by security_operation, then calculate and reserve the meta data and clusters needed by this security xattr before starting transaction, finally set it before add_entry.
--- fs/ocfs2/namei.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++------ fs/ocfs2/xattr.c | 70 +++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.h | 17 +++++++++ 3 files changed, 182 insertions(+), 12 deletions(-)
fs/ocfs2/namei.c +95 -12
@@ -229,6 +229,12 @@ static int ocfs2_mknod(struct inode *dir,struct inode *inode =NULL ;struct ocfs2_alloc_context *inode_ac =NULL ;struct ocfs2_alloc_context *data_ac =NULL ; +struct ocfs2_alloc_context *xattr_ac =NULL ; +int want_clusters =0 ; +int xattr_credits =0 ; +struct ocfs2_security_xattr_info si = { + .enable =1 , + }; mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, (unsigned long)dev, dentry->d_name.len,
@@ -285,17 +291,39 @@ static int ocfs2_mknod(struct inode *dir, goto leave; } -/* Reserve a cluster if creating an extent based directory. */ -if (S_ISDIR (mode) && !ocfs2_supports_inline_data (osb)) { - status =ocfs2_reserve_clusters (osb,1 , &data_ac); +/* get security xattr */ + status =ocfs2_init_security_get (inode, dir, &si); +if (status) { +if (status == -EOPNOTSUPP ) + si.enable =0 ; +else { +mlog_errno (status); + goto leave; + } + } + +/* calculate meta data/clusters for setting security xattr */ +if (si.enable) { + status =ocfs2_calc_security_init (dir, &si, &want_clusters, + &xattr_credits, &xattr_ac);if (status <0 ) { -if (status != -ENOSPC ) -mlog_errno (status); +mlog_errno (status); goto leave; } } - handle =ocfs2_start_trans (osb,OCFS2_MKNOD_CREDITS ); +/* Reserve a cluster if creating an extent based directory. */ +if (S_ISDIR (mode) && !ocfs2_supports_inline_data (osb)) + want_clusters +=1 ; + + status =ocfs2_reserve_clusters (osb, want_clusters, &data_ac); +if (status <0 ) { +if (status != -ENOSPC ) +mlog_errno (status); + goto leave; + } + + handle =ocfs2_start_trans (osb,OCFS2_MKNOD_CREDITS + xattr_credits);if (IS_ERR (handle)) { status =PTR_ERR (handle); handle =NULL ;
@@ -335,6 +363,15 @@ static int ocfs2_mknod(struct inode *dir,inc_nlink (dir); } +if (si.enable) { + status =ocfs2_init_security_set (handle, inode, new_fe_bh, &si, + xattr_ac, data_ac); +if (status <0 ) { +mlog_errno (status); + goto leave; + } + } + status =ocfs2_add_entry (handle, dentry, inode,OCFS2_I (inode)->ip_blkno, parent_fe_bh, de_bh);
@@ -366,6 +403,8 @@ leave:brelse (new_fe_bh);brelse (de_bh);brelse (parent_fe_bh); +kfree (si.name); +kfree (si.value);if ((status <0 ) && inode) {clear_nlink (inode);
@@ -378,6 +417,9 @@ leave:if (data_ac)ocfs2_free_alloc_context (data_ac); +if (xattr_ac) +ocfs2_free_alloc_context (xattr_ac); +mlog_exit (status);return status;
@@ -1508,6 +1550,12 @@ static int ocfs2_symlink(struct inode *dir,handle_t *handle =NULL ;struct ocfs2_alloc_context *inode_ac =NULL ;struct ocfs2_alloc_context *data_ac =NULL ; +struct ocfs2_alloc_context *xattr_ac =NULL ; +int want_clusters =0 ; +int xattr_credits =0 ; +struct ocfs2_security_xattr_info si = { + .enable =1 , + };mlog_entry ("(0x%p, 0x%p, symname='%s' actual='%.*s')\n" , dir, dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1561,17 +1609,39 @@ static int ocfs2_symlink(struct inode *dir, goto bail; } -/* don't reserve bitmap space for fast symlinks. */ -if (l >ocfs2_fast_symlink_chars (sb)) { - status =ocfs2_reserve_clusters (osb,1 , &data_ac); +/* get security xattr */ + status =ocfs2_init_security_get (inode, dir, &si); +if (status) { +if (status == -EOPNOTSUPP ) + si.enable =0 ; +else { +mlog_errno (status); + goto bail; + } + } + +/* calculate meta data/clusters for setting security xattr */ +if (si.enable) { + status =ocfs2_calc_security_init (dir, &si, &want_clusters, + &xattr_credits, &xattr_ac);if (status <0 ) { -if (status != -ENOSPC ) -mlog_errno (status); +mlog_errno (status); goto bail; } } - handle =ocfs2_start_trans (osb, credits); +/* don't reserve bitmap space for fast symlinks. */ +if (l >ocfs2_fast_symlink_chars (sb)) + want_clusters +=1 ; + + status =ocfs2_reserve_clusters (osb, want_clusters, &data_ac); +if (status <0 ) { +if (status != -ENOSPC ) +mlog_errno (status); + goto bail; + } + + handle =ocfs2_start_trans (osb, credits + xattr_credits);if (IS_ERR (handle)) { status =PTR_ERR (handle); handle =NULL ;
@@ -1632,6 +1702,15 @@ static int ocfs2_symlink(struct inode *dir, } } +if (si.enable) { + status =ocfs2_init_security_set (handle, inode, new_fe_bh, &si, + xattr_ac, data_ac); +if (status <0 ) { +mlog_errno (status); + goto bail; + } + } + status =ocfs2_add_entry (handle, dentry, inode,le64_to_cpu (fe->i_blkno), parent_fe_bh, de_bh);
@@ -1658,10 +1737,14 @@ bail:brelse (new_fe_bh);brelse (parent_fe_bh);brelse (de_bh); +kfree (si.name); +kfree (si.value);if (inode_ac)ocfs2_free_alloc_context (inode_ac);if (data_ac)ocfs2_free_alloc_context (data_ac); +if (xattr_ac) +ocfs2_free_alloc_context (xattr_ac);if ((status <0 ) && inode) {clear_nlink (inode);iput (inode);
fs/ocfs2/xattr.c +70 -0
88 lines not on this page · raw message
fs/ocfs2/xattr.h +17 -0
@@ -30,6 +30,13 @@ enum ocfs2_xattr_type { OCFS2_XATTR_MAX }; +struct ocfs2_security_xattr_info { +int enable; +char *name; +void *value; +size_t value_len; +}; +extern struct xattr_handler ocfs2_xattr_user_handler;extern struct xattr_handler ocfs2_xattr_trusted_handler;extern struct xattr_handler ocfs2_xattr_security_handler;
@@ -43,5 +50,15 @@ int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *, struct ocfs2_alloc_context *, struct ocfs2_alloc_context *);int ocfs2_xattr_remove (struct inode *,struct buffer_head *); +int ocfs2_init_security_get (struct inode *,struct inode *, +struct ocfs2_security_xattr_info *); +int ocfs2_init_security_set (handle_t *,struct inode *, +struct buffer_head *, +struct ocfs2_security_xattr_info *, +struct ocfs2_alloc_context *, +struct ocfs2_alloc_context *); +int ocfs2_calc_security_init (struct inode *, +struct ocfs2_security_xattr_info *, +int *,int *,struct ocfs2_alloc_context **);#endif /* OCFS2_XATTR_H */
Signature · 1 line
1.5.4.1
PATCH 5/10 ocfs2: add ocfs2_xattr_get_nolock
In reply to Tiger YangThis function do the work of ocfs2_xattr_get under an opend lock.
--- fs/ocfs2/xattr.c | 40 ++++++++++++++++++++++++++++------------ fs/ocfs2/xattr.h | 2 ++ 2 files changed, 30 insertions(+), 12 deletions(-)
fs/ocfs2/xattr.c +28 -12
@@ -925,12 +925,8 @@ cleanup:return ret; } -/* ocfs2_xattr_get() -* -* Copy an extended attribute into the buffer provided. -* Buffer is NULL to compute the size of buffer required. -*/ -static int ocfs2_xattr_get(struct inode *inode, +int ocfs2_xattr_get_nolock(struct inode *inode, + struct buffer_head *di_bh, int name_index, const char *name, void *buffer,
@@ -938,7 +934,6 @@ static int ocfs2_xattr_get(struct inode *inode, {int ret;struct ocfs2_dinode *di =NULL ; -struct buffer_head *di_bh =NULL ;struct ocfs2_inode_info *oi =OCFS2_I (inode);struct ocfs2_xattr_search xis = { .not_found = -ENODATA ,
@@ -953,11 +948,6 @@ static int ocfs2_xattr_get(struct inode *inode,if (!(oi->ip_dyn_features &OCFS2_HAS_XATTR_FL )) ret = -ENODATA ; - ret =ocfs2_inode_lock (inode, &di_bh,0 ); -if (ret <0 ) { -mlog_errno (ret); -return ret; - } xis.inode_bh = xbs.inode_bh = di_bh; di = (struct ocfs2_dinode *)di_bh->b_data;
@@ -968,6 +958,32 @@ static int ocfs2_xattr_get(struct inode *inode, ret =ocfs2_xattr_block_get (inode, name_index, name, buffer, buffer_size, &xbs);up_read (&oi->ip_xattr_sem); + +return ret; +} + +/* ocfs2_xattr_get() +* +* Copy an extended attribute into the buffer provided. +* Buffer is NULL to compute the size of buffer required. +*/ +static int ocfs2_xattr_get (struct inode *inode, +int name_index, +const char *name, +void *buffer, +size_t buffer_size) +{ +int ret; +struct buffer_head *di_bh =NULL ; + + ret =ocfs2_inode_lock (inode, &di_bh,0 ); +if (ret <0 ) { +mlog_errno (ret); +return ret; + } + ret =ocfs2_xattr_get_nolock (inode, di_bh, name_index, + name, buffer, buffer_size); +ocfs2_inode_unlock (inode,0 );brelse (di_bh);
fs/ocfs2/xattr.h +2 -0
@@ -43,6 +43,8 @@ extern struct xattr_handler ocfs2_xattr_security_handler;extern struct xattr_handler *ocfs2_xattr_handlers[];ssize_t ocfs2_listxattr (struct dentry *,char *,size_t ); +int ocfs2_xattr_get_nolock (struct inode *,struct buffer_head *,int , +const char *,void *,size_t );int ocfs2_xattr_set (struct inode *,int ,const char *,const void *,size_t ,int ); int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *,
Signature · 1 line
1.5.4.1
PATCH 6/10 ocfs2: add POSIX ACL API
In reply to Tiger YangThis patch add POSIX ACL(access control lists) APIs in ocfs2. we convert struct posix_acl to many ocfs2_acl_entry and regard them as an extended attribute entry.
--- fs/ocfs2/Makefile | 4 + fs/ocfs2/acl.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/acl.h | 29 ++++ fs/ocfs2/ocfs2.h | 1 + fs/ocfs2/xattr.c | 10 ++ fs/ocfs2/xattr.h | 4 + 6 files changed, 426 insertions(+), 0 deletions(-) create mode 100644 fs/ocfs2/acl.c create mode 100644 fs/ocfs2/acl.h
fs/ocfs2/Makefile +4 -0
@@ -37,6 +37,10 @@ ocfs2-objs := \ ver.o \ xattr.o +ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y) +ocfs2-objs += acl.o +endif + ocfs2_stackglue-objs := stackglue.o ocfs2_stack_o2cb-objs := stack_o2cb.o ocfs2_stack_user-objs := stack_user.o
fs/ocfs2/acl.c new file +378 -0
378 lines not on this page · raw message
fs/ocfs2/acl.h new file +29 -0
@@ -0,0 +1,29 @@ +/* -*- mode: c; c-basic-offset: 8; -*- +* vim: noexpandtab sw=8 ts=8 sts=0: +* +* acl.h +* +* Copyright (C) 2004, 2008 Oracle. All rights reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License version 2 as published by the Free Software Foundation. +* +* This program 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. +*/ + +#ifndef OCFS2_ACL_H +#define OCFS2_ACL_H + +#include <linux/posix_acl_xattr.h> + +struct ocfs2_acl_entry { +__le16 e_tag; +__le16 e_perm; +__le32 e_id; +}; + +#endif /* OCFS2_ACL_H */
fs/ocfs2/ocfs2.h +1 -0
@@ -195,6 +195,7 @@ enum ocfs2_mount_optionsOCFS2_MOUNT_LOCALFLOCKS =1 <<5 ,/* No cluster aware user file locks */ OCFS2_MOUNT_NOUSERXATTR =1 <<6 ,/* No user xattr */ OCFS2_MOUNT_INODE64 =1 <<7 ,/* Allow inode numbers > 2^32 */ + OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */ };#define OCFS2_OSB_SOFT_RO 0x0001
fs/ocfs2/xattr.c +10 -0
@@ -91,6 +91,10 @@ static struct ocfs2_xattr_def_value_root def_xv = {struct xattr_handler *ocfs2_xattr_handlers[] = { &ocfs2_xattr_user_handler, +#ifdef CONFIG_OCFS2_FS_POSIX_ACL + &ocfs2_xattr_acl_access_handler, + &ocfs2_xattr_acl_default_handler, +#endif &ocfs2_xattr_trusted_handler, &ocfs2_xattr_security_handler,NULL
@@ -98,6 +102,12 @@ struct xattr_handler *ocfs2_xattr_handlers[] = {static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX ] = { [OCFS2_XATTR_INDEX_USER ] = &ocfs2_xattr_user_handler, +#ifdef CONFIG_OCFS2_FS_POSIX_ACL + [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS ] + = &ocfs2_xattr_acl_access_handler, + [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT ] + = &ocfs2_xattr_acl_default_handler, +#endif [OCFS2_XATTR_INDEX_TRUSTED ] = &ocfs2_xattr_trusted_handler, [OCFS2_XATTR_INDEX_SECURITY ] = &ocfs2_xattr_security_handler, };
fs/ocfs2/xattr.h +4 -0
@@ -40,6 +40,10 @@ struct ocfs2_security_xattr_info {extern struct xattr_handler ocfs2_xattr_user_handler;extern struct xattr_handler ocfs2_xattr_trusted_handler;extern struct xattr_handler ocfs2_xattr_security_handler; +#ifdef CONFIG_OCFS2_FS_POSIX_ACL +extern struct xattr_handler ocfs2_xattr_acl_access_handler; +extern struct xattr_handler ocfs2_xattr_acl_default_handler; +#endif extern struct xattr_handler *ocfs2_xattr_handlers[];ssize_t ocfs2_listxattr (struct dentry *,char *,size_t );
Signature · 1 line
1.5.4.1
PATCH 7/10 ocfs2: add ocfs2_check_acl
In reply to Tiger YangThis functions use to enhance permission checking with POSIX ACL.
--- fs/ocfs2/acl.c | 15 +++++++++++++++ fs/ocfs2/acl.h | 10 ++++++++++ fs/ocfs2/file.c | 3 ++- 3 files changed, 27 insertions(+), 1 deletions(-)
fs/ocfs2/acl.c +15 -0
@@ -230,6 +230,21 @@ static int ocfs2_set_acl(handle_t *handle,return ret; } +int ocfs2_check_acl (struct inode *inode,int mask) +{ +struct posix_acl *acl =ocfs2_get_acl (inode,ACL_TYPE_ACCESS ); + +if (IS_ERR (acl)) +return PTR_ERR (acl); +if (acl) { +int ret =posix_acl_permission (inode, acl, mask); +posix_acl_release (acl); +return ret; + } + +return -EAGAIN ; +} + static size_t ocfs2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
fs/ocfs2/acl.h +10 -0
@@ -26,4 +26,14 @@ struct ocfs2_acl_entry { __le32 e_id; }; +#ifdef CONFIG_OCFS2_FS_POSIX_ACL + +extern int ocfs2_check_acl (struct inode *,int ); + +#else /* CONFIG_OCFS2_FS_POSIX_ACL*/ + +#define ocfs2_check_acl NULL + +#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/ +#endif /* OCFS2_ACL_H */
fs/ocfs2/file.c +2 -1
@@ -56,6 +56,7 @@#include "suballoc.h" #include "super.h" #include "xattr.h" +#include "acl.h" #include "buffer_head_io.h"
@@ -1035,7 +1036,7 @@ int ocfs2_permission(struct inode *inode, int mask) goto out; } - ret =generic_permission (inode, mask,NULL ); + ret =generic_permission (inode, mask, ocfs2_check_acl);ocfs2_inode_unlock (inode,0 ); out:
Signature · 1 line
1.5.4.1
PATCH 8/10 ocfs2: add ocfs2_acl_chmod
In reply to Tiger YangThis function use to update acl xattrs when file mode was changed.
--- fs/ocfs2/acl.c | 27 +++++++++++++++++++++++++++ fs/ocfs2/acl.h | 5 +++++ fs/ocfs2/file.c | 6 ++++++ 3 files changed, 38 insertions(+), 0 deletions(-)
fs/ocfs2/acl.c +27 -0
@@ -245,6 +245,33 @@ int ocfs2_check_acl(struct inode *inode, int mask)return -EAGAIN ; } +int ocfs2_acl_chmod (struct inode *inode) +{ +struct ocfs2_super *osb =OCFS2_SB (inode->i_sb); +struct posix_acl *acl, *clone; +int ret; + +if (S_ISLNK (inode->i_mode)) +return -EOPNOTSUPP ; + +if (!(osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL )) +return 0 ; + + acl =ocfs2_get_acl (inode,ACL_TYPE_ACCESS ); +if (IS_ERR (acl) || !acl) +return PTR_ERR (acl); + clone =posix_acl_clone (acl,GFP_KERNEL ); +posix_acl_release (acl); +if (!clone) +return -ENOMEM ; + ret =posix_acl_chmod_masq (clone, inode->i_mode); +if (!ret) + ret =ocfs2_set_acl (NULL , inode,NULL ,ACL_TYPE_ACCESS , + clone,NULL ,NULL ); +posix_acl_release (clone); +return ret; +} + static size_t ocfs2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
fs/ocfs2/acl.h +5 -0
@@ -29,10 +29,15 @@ struct ocfs2_acl_entry {#ifdef CONFIG_OCFS2_FS_POSIX_ACL extern int ocfs2_check_acl (struct inode *,int ); +extern int ocfs2_acl_chmod (struct inode *);#else /* CONFIG_OCFS2_FS_POSIX_ACL*/ #define ocfs2_check_acl NULL +static inline int ocfs2_acl_chmod (struct inode *inode) +{ +return 0 ; +}#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/
fs/ocfs2/file.c +6 -0
@@ -990,6 +990,12 @@ bail_unlock_rw: bail:brelse (bh); +if (!status && attr->ia_valid &ATTR_MODE ) { + status =ocfs2_acl_chmod (inode); +if (status <0 ) +mlog_errno (status); + } +mlog_exit (status);return status; }
Signature · 1 line
1.5.4.1
PATCH 9/10 ocfs2: add ocfs2_init_acl in mknod
In reply to Tiger YangThis function get the parent directory's acl, and let the child inherit it. We must calculate and reserve metadata and clusters for it need.
--- fs/ocfs2/acl.c | 59 ++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/acl.h | 14 +++++++++ fs/ocfs2/namei.c | 23 ++++++++++----- fs/ocfs2/xattr.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.h | 3 ++ 5 files changed, 170 insertions(+), 8 deletions(-)
fs/ocfs2/acl.c +59 -0
@@ -272,6 +272,65 @@ int ocfs2_acl_chmod(struct inode *inode)return ret; } +/* +* Initialize the ACLs of a new inode. If parent directory has default ACL, +* then clone to new inode. Called from ocfs2_mknod. +*/ +int ocfs2_init_acl (handle_t *handle, +struct inode *inode, +struct inode *dir, +struct buffer_head *di_bh, +struct buffer_head *dir_bh, +struct ocfs2_alloc_context *meta_ac, +struct ocfs2_alloc_context *data_ac) +{ +struct ocfs2_super *osb =OCFS2_SB (inode->i_sb); +struct posix_acl *acl =NULL ; +int ret =0 ; + +if (!S_ISLNK (inode->i_mode)) { +if (osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) { + acl =ocfs2_get_acl_nolock (dir,ACL_TYPE_DEFAULT , + dir_bh); +if (IS_ERR (acl)) +return PTR_ERR (acl); + } +if (!acl) + inode->i_mode &= ~current->fs->umask; + } +if ((osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) && acl) { +struct posix_acl *clone; +mode_t mode; + +if (S_ISDIR (inode->i_mode)) { + ret =ocfs2_set_acl (handle, inode, di_bh, +ACL_TYPE_DEFAULT , acl, + meta_ac, data_ac); +if (ret) + goto cleanup; + } + clone =posix_acl_clone (acl,GFP_NOFS ); + ret = -ENOMEM ; +if (!clone) + goto cleanup; + + mode = inode->i_mode; + ret =posix_acl_create_masq (clone, &mode); +if (ret >=0 ) { + inode->i_mode = mode; +if (ret >0 ) { + ret =ocfs2_set_acl (handle, inode, + di_bh,ACL_TYPE_ACCESS , + clone, meta_ac, data_ac); + } + } +posix_acl_release (clone); + } +cleanup: +posix_acl_release (acl); +return ret; +} + static size_t ocfs2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
fs/ocfs2/acl.h +14 -0
@@ -30,6 +30,10 @@ struct ocfs2_acl_entry {extern int ocfs2_check_acl (struct inode *,int );extern int ocfs2_acl_chmod (struct inode *); +extern int ocfs2_init_acl (handle_t *,struct inode *,struct inode *, +struct buffer_head *,struct buffer_head *, +struct ocfs2_alloc_context *, +struct ocfs2_alloc_context *);#else /* CONFIG_OCFS2_FS_POSIX_ACL*/
@@ -38,6 +42,16 @@ static inline int ocfs2_acl_chmod(struct inode *inode) {return 0 ; } +static inline int ocfs2_init_acl (handle_t *handle, +struct inode *inode, +struct inode *dir, +struct buffer_head *di_bh, +struct buffer_head *dir_bh, +struct ocfs2_alloc_context *meta_ac, +struct ocfs2_alloc_context *data_ac) +{ +return 0 ; +}#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/
fs/ocfs2/namei.c +15 -8
@@ -61,6 +61,7 @@#include "sysfile.h" #include "uptodate.h" #include "xattr.h" +#include "acl.h" #include "buffer_head_io.h"
@@ -302,14 +303,13 @@ static int ocfs2_mknod(struct inode *dir, } } -/* calculate meta data/clusters for setting security xattr */ -if (si.enable) { - status =ocfs2_calc_security_init (dir, &si, &want_clusters, - &xattr_credits, &xattr_ac); -if (status <0 ) { -mlog_errno (status); - goto leave; - } +/* calculate meta data/clusters for setting security and acl xattr */ + status =ocfs2_calc_xattr_init (dir, parent_fe_bh, mode, + &si, &want_clusters, + &xattr_credits, &xattr_ac); +if (status <0 ) { +mlog_errno (status); + goto leave; }/* Reserve a cluster if creating an extent based directory. */
@@ -363,6 +363,13 @@ static int ocfs2_mknod(struct inode *dir,inc_nlink (dir); } + status =ocfs2_init_acl (handle, inode, dir, new_fe_bh, parent_fe_bh, + xattr_ac, data_ac); +if (status <0 ) { +mlog_errno (status); + goto leave; + } +if (si.enable) { status =ocfs2_init_security_set (handle, inode, new_fe_bh, &si, xattr_ac, data_ac);
fs/ocfs2/xattr.c +79 -0
91 lines not on this page · raw message
fs/ocfs2/xattr.h +3 -0
@@ -66,5 +66,8 @@ int ocfs2_init_security_set(handle_t *, struct inode *,int ocfs2_calc_security_init (struct inode *,struct ocfs2_security_xattr_info *,int *,int *,struct ocfs2_alloc_context **); +int ocfs2_calc_xattr_init (struct inode *,struct buffer_head *, +int ,struct ocfs2_security_xattr_info *, +int *,int *,struct ocfs2_alloc_context **);#endif /* OCFS2_XATTR_H */
Signature · 1 line
1.5.4.1
PATCH 10/10 ocfs2: add mount option and Kconfig option for acl
In reply to Tiger YangThis patch add Kconfig option "CONFIG_OCFS2_FS_POSIX_ACL" and mount option "acl" for enable acl.
--- Documentation/filesystems/ocfs2.txt | 4 ++-- fs/Kconfig | 9 +++++++++ fs/ocfs2/super.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-)
Documentation/filesystems/ocfs2.txt +2 -2
@@ -28,13 +28,11 @@ Manish Singh <[email protected]> Caveats ======= Features which OCFS2 does not support yet: - - extended attributes - quotas - cluster aware flock - cluster aware lockf - Directory change notification (F_NOTIFY) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - - POSIX ACLs Mount options =============
@@ -82,3 +80,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at bits of significance. user_xattr (*) Enables Extended User Attributes. nouser_xattr Disables Extended User Attributes. +acl Enables POSIX Access Control Lists support. +noacl (*) Disables POSIX Access Control Lists support.
fs/Kconfig +9 -0
@@ -268,6 +268,15 @@ config OCFS2_COMPAT_JBD is backwards compatible with JBD. It is safe to say N here. However, if you really want to use the original JBD, say Y here. +config OCFS2_FS_POSIX_ACL + bool "OCFS2 POSIX Access Control Lists" + depends on OCFS2_FS + select FS_POSIX_ACL + default n + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + endif # BLOCK config DNOTIFY
fs/ocfs2/super.c +33 -0
@@ -158,6 +158,8 @@ enum { Opt_user_xattr, Opt_nouser_xattr, Opt_inode64, + Opt_acl, + Opt_noacl, Opt_err, };
@@ -180,6 +182,8 @@ static const match_table_t tokens = { {Opt_user_xattr, "user_xattr"}, {Opt_nouser_xattr, "nouser_xattr"}, {Opt_inode64, "inode64"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, {Opt_err, NULL} };
@@ -466,6 +470,8 @@ unlock_osb:if (!ret) {/* Only save off the new mount options in case of a successful * remount. */ +if (!(osb->s_feature_incompat &OCFS2_FEATURE_INCOMPAT_XATTR )) + parsed_options.mount_opt &= ~OCFS2_MOUNT_POSIX_ACL ; osb->s_mount_opt = parsed_options.mount_opt; osb->s_atime_quantum = parsed_options.atime_quantum; osb->preferred_slot = parsed_options.slot;
@@ -651,6 +657,10 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) }brelse (bh); bh =NULL ; + +if (!(osb->s_feature_incompat &OCFS2_FEATURE_INCOMPAT_XATTR )) + parsed_options.mount_opt &= ~OCFS2_MOUNT_POSIX_ACL ; + osb->s_mount_opt = parsed_options.mount_opt; osb->s_atime_quantum = parsed_options.atime_quantum; osb->preferred_slot = parsed_options.slot;
@@ -664,6 +674,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) sb->s_magic =OCFS2_SUPER_MAGIC ; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL ) | + ((osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) ?MS_POSIXACL :0 ); +/* Hard readonly mode only if: bdev_read_only, MS_RDONLY, * heartbeat=none */ if (bdev_read_only (sb->s_bdev)) {
@@ -945,6 +958,19 @@ static int ocfs2_parse_options(struct super_block *sb,case Opt_inode64: mopt->mount_opt |=OCFS2_MOUNT_INODE64 ;break ; +#ifdef CONFIG_OCFS2_FS_POSIX_ACL +case Opt_acl: + mopt->mount_opt |=OCFS2_MOUNT_POSIX_ACL ; +break ; +case Opt_noacl: + mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL ; +break ; +#else +case Opt_acl: +case Opt_noacl: +printk (KERN_INFO "ocfs2 (no)acl options not supported\n" ); +break ; +#endif default :mlog (ML_ERROR , "Unrecognized mount option \"%s\" "
@@ -1017,6 +1043,13 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)if (opts &OCFS2_MOUNT_INODE64 )seq_printf (s,",inode64" ); +#ifdef CONFIG_OCFS2_FS_POSIX_ACL +if (opts &OCFS2_MOUNT_POSIX_ACL ) +seq_printf (s,",acl" ); +else +seq_printf (s,",noacl" ); +#endif +return 0 ; }
Signature · 1 line
1.5.4.1
cover ocfs2: add security EA and ACL support V5
In reply to Tiger YangQuoted 3 lines · Tiger Yang
This the 5th version for add security EA and acl support in ocfs2. In this round I fixed many problem as Mark commented. Them based on Mark's
merge_windowbranch.
Great! Thanks for this Tiger. The patches are in Ocfs2.git now.
--Mark
--
Mark Fasheh