[GFS2] selinux support
This adds support to GFS2 for selinux extended attributes. There is a known bug in gfs2_ea_get() which is believed to be independant of this patch. Further patches will follow once that bug is fixed in order to make GFS2 use as much of the generic eattr infrastructure as possible. Signed-off-by: Ryan O'Hara <rohara@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
d2f222e631
commit
639b6d79b8
|
@ -43,6 +43,10 @@ unsigned int gfs2_ea_name2type(const char *name, char **truncated_name)
|
||||||
type = GFS2_EATYPE_USR;
|
type = GFS2_EATYPE_USR;
|
||||||
if (truncated_name)
|
if (truncated_name)
|
||||||
*truncated_name = strchr(name, '.') + 1;
|
*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 {
|
} else {
|
||||||
type = GFS2_EATYPE_UNUSED;
|
type = GFS2_EATYPE_UNUSED;
|
||||||
if (truncated_name)
|
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);
|
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 = {
|
static struct gfs2_eattr_operations gfs2_user_eaops = {
|
||||||
.eo_get = user_eo_get,
|
.eo_get = user_eo_get,
|
||||||
.eo_set = user_eo_set,
|
.eo_set = user_eo_set,
|
||||||
|
@ -180,6 +214,13 @@ struct gfs2_eattr_operations gfs2_system_eaops = {
|
||||||
.eo_name = "system",
|
.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[] = {
|
struct gfs2_eattr_operations *gfs2_ea_ops[] = {
|
||||||
NULL,
|
NULL,
|
||||||
&gfs2_user_eaops,
|
&gfs2_user_eaops,
|
||||||
|
|
|
@ -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_system_eaops;
|
||||||
|
|
||||||
|
extern struct gfs2_eattr_operations gfs2_security_eaops;
|
||||||
|
|
||||||
extern struct gfs2_eattr_operations *gfs2_ea_ops[];
|
extern struct gfs2_eattr_operations *gfs2_ea_ops[];
|
||||||
|
|
||||||
#endif /* __EAOPS_DOT_H__ */
|
#endif /* __EAOPS_DOT_H__ */
|
||||||
|
|
|
@ -368,7 +368,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct buffer_head *bh,
|
||||||
{
|
{
|
||||||
struct ea_list *ei = private;
|
struct ea_list *ei = private;
|
||||||
struct gfs2_ea_request *er = ei->ei_er;
|
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)
|
if (ea->ea_type == GFS2_EATYPE_UNUSED)
|
||||||
return 0;
|
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)
|
if (ei->ei_size + ea_size > er->er_data_len)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
if (ea->ea_type == GFS2_EATYPE_USR) {
|
switch (ea->ea_type) {
|
||||||
|
case GFS2_EATYPE_USR:
|
||||||
prefix = "user.";
|
prefix = "user.";
|
||||||
l = 5;
|
l = 5;
|
||||||
} else {
|
break;
|
||||||
|
case GFS2_EATYPE_SYS:
|
||||||
prefix = "system.";
|
prefix = "system.";
|
||||||
l = 7;
|
l = 7;
|
||||||
|
break;
|
||||||
|
case GFS2_EATYPE_SECURITY:
|
||||||
|
prefix = "security.";
|
||||||
|
l = 9;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(er->er_data + ei->ei_size,
|
memcpy(er->er_data + ei->ei_size,
|
||||||
|
|
|
@ -18,9 +18,6 @@ ALIGN(sizeof(struct gfs2_ea_header) + (ea)->ea_name_len + \
|
||||||
((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \
|
((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \
|
||||||
(sizeof(uint64_t) * (ea)->ea_num_ptrs)), 8)
|
(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_STUFFED(ea) (!(ea)->ea_num_ptrs)
|
||||||
#define GFS2_EA_IS_LAST(ea) ((ea)->ea_flags & GFS2_EAFLAG_LAST)
|
#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,
|
int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el,
|
||||||
struct iattr *attr, char *data);
|
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__ */
|
#endif /* __EATTR_DOT_H__ */
|
||||||
|
|
|
@ -311,8 +311,9 @@ struct gfs2_leaf {
|
||||||
#define GFS2_EATYPE_UNUSED 0
|
#define GFS2_EATYPE_UNUSED 0
|
||||||
#define GFS2_EATYPE_USR 1
|
#define GFS2_EATYPE_USR 1
|
||||||
#define GFS2_EATYPE_SYS 2
|
#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_EATYPE_VALID(x) ((x) <= GFS2_EATYPE_LAST)
|
||||||
|
|
||||||
#define GFS2_EAFLAG_LAST 0x01 /* last ea in block */
|
#define GFS2_EAFLAG_LAST 0x01 /* last ea in block */
|
||||||
|
|
Loading…
Reference in New Issue