diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index 85c1dbace88b..2243b44ecb07 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c @@ -43,6 +43,10 @@ unsigned int gfs2_ea_name2type(const char *name, char **truncated_name) type = GFS2_EATYPE_USR; if (truncated_name) *truncated_name = strchr(name, '.') + 1; + } else if (strncmp(name, "security.", 9) == 0) { + type = GFS2_EATYPE_SECURITY; + if (truncated_name) + *truncated_name = strchr(name, '.') + 1; } else { type = GFS2_EATYPE_UNUSED; if (truncated_name) @@ -166,6 +170,36 @@ static int system_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) return gfs2_ea_remove_i(ip, er); } +static int security_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er) +{ + struct inode *inode = ip->i_vnode; + int error = permission(inode, MAY_READ, NULL); + if (error) + return error; + + return gfs2_ea_get_i(ip, er); +} + +static int security_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er) +{ + struct inode *inode = ip->i_vnode; + int error = permission(inode, MAY_WRITE, NULL); + if (error) + return error; + + return gfs2_ea_set_i(ip, er); +} + +static int security_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) +{ + struct inode *inode = ip->i_vnode; + int error = permission(inode, MAY_WRITE, NULL); + if (error) + return error; + + return gfs2_ea_remove_i(ip, er); +} + static struct gfs2_eattr_operations gfs2_user_eaops = { .eo_get = user_eo_get, .eo_set = user_eo_set, @@ -180,6 +214,13 @@ struct gfs2_eattr_operations gfs2_system_eaops = { .eo_name = "system", }; +struct gfs2_eattr_operations gfs2_security_eaops = { + .eo_get = security_eo_get, + .eo_set = security_eo_set, + .eo_remove = security_eo_remove, + .eo_name = "security", +}; + struct gfs2_eattr_operations *gfs2_ea_ops[] = { NULL, &gfs2_user_eaops, diff --git a/fs/gfs2/eaops.h b/fs/gfs2/eaops.h index 3dece17e3116..965a235c96e8 100644 --- a/fs/gfs2/eaops.h +++ b/fs/gfs2/eaops.h @@ -23,6 +23,8 @@ unsigned int gfs2_ea_name2type(const char *name, char **truncated_name); extern struct gfs2_eattr_operations gfs2_system_eaops; +extern struct gfs2_eattr_operations gfs2_security_eaops; + extern struct gfs2_eattr_operations *gfs2_ea_ops[]; #endif /* __EAOPS_DOT_H__ */ diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index f5169a42a919..187fba1c4678 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -368,7 +368,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct buffer_head *bh, { struct ea_list *ei = private; struct gfs2_ea_request *er = ei->ei_er; - unsigned int ea_size = GFS2_EA_STRLEN(ea); + unsigned int ea_size = gfs2_ea_strlen(ea); if (ea->ea_type == GFS2_EATYPE_UNUSED) return 0; @@ -381,12 +381,21 @@ static int ea_list_i(struct gfs2_inode *ip, struct buffer_head *bh, if (ei->ei_size + ea_size > er->er_data_len) return -ERANGE; - if (ea->ea_type == GFS2_EATYPE_USR) { + switch (ea->ea_type) { + case GFS2_EATYPE_USR: prefix = "user."; l = 5; - } else { + break; + case GFS2_EATYPE_SYS: prefix = "system."; l = 7; + break; + case GFS2_EATYPE_SECURITY: + prefix = "security."; + l = 9; + break; + default: + break; } memcpy(er->er_data + ei->ei_size, diff --git a/fs/gfs2/eattr.h b/fs/gfs2/eattr.h index 19fb1dc4ddc4..ae199692e51d 100644 --- a/fs/gfs2/eattr.h +++ b/fs/gfs2/eattr.h @@ -18,9 +18,6 @@ ALIGN(sizeof(struct gfs2_ea_header) + (ea)->ea_name_len + \ ((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \ (sizeof(uint64_t) * (ea)->ea_num_ptrs)), 8) -#define GFS2_EA_STRLEN(ea) \ -((((ea)->ea_type == GFS2_EATYPE_USR) ? 5 : 7) + (ea)->ea_name_len + 1) - #define GFS2_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs) #define GFS2_EA_IS_LAST(ea) ((ea)->ea_flags & GFS2_EAFLAG_LAST) @@ -83,4 +80,18 @@ int gfs2_ea_get_copy(struct gfs2_inode *ip, int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, struct iattr *attr, char *data); +static inline unsigned int gfs2_ea_strlen(struct gfs2_ea_header *ea) +{ + switch (ea->ea_type) { + case GFS2_EATYPE_USR: + return (5 + (ea->ea_name_len + 1)); + case GFS2_EATYPE_SYS: + return (7 + (ea->ea_name_len + 1)); + case GFS2_EATYPE_SECURITY: + return (9 + (ea->ea_name_len + 1)); + default: + return (0); + } +} + #endif /* __EATTR_DOT_H__ */ diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 4356e3864643..3893aac4e3ae 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -311,8 +311,9 @@ struct gfs2_leaf { #define GFS2_EATYPE_UNUSED 0 #define GFS2_EATYPE_USR 1 #define GFS2_EATYPE_SYS 2 +#define GFS2_EATYPE_SECURITY 3 -#define GFS2_EATYPE_LAST 2 +#define GFS2_EATYPE_LAST 3 #define GFS2_EATYPE_VALID(x) ((x) <= GFS2_EATYPE_LAST) #define GFS2_EAFLAG_LAST 0x01 /* last ea in block */