aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/eaops.c41
-rw-r--r--fs/gfs2/eaops.h2
-rw-r--r--fs/gfs2/eattr.c15
-rw-r--r--fs/gfs2/eattr.h17
-rw-r--r--include/linux/gfs2_ondisk.h3
5 files changed, 71 insertions, 7 deletions
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index 85c1dbace88..2243b44ecb0 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 3dece17e311..965a235c96e 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 f5169a42a91..187fba1c467 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 19fb1dc4ddc..ae199692e51 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 4356e386464..3893aac4e3a 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 */