1/* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4 * 5 * This copyrighted material is made available to anyone wishing to use, 6 * modify, copy, or redistribute it subject to the terms and conditions 7 * of the GNU General Public License version 2. 8 */ 9 10#include <linux/slab.h> 11#include <linux/spinlock.h> 12#include <linux/completion.h> 13#include <linux/buffer_head.h> 14#include <linux/xattr.h> 15#include <linux/gfs2_ondisk.h> 16#include <linux/lm_interface.h> 17#include <asm/uaccess.h> 18 19#include "gfs2.h" 20#include "incore.h" 21#include "acl.h" 22#include "eaops.h" 23#include "eattr.h" 24#include "util.h" 25 26/** 27 * gfs2_ea_name2type - get the type of the ea, and truncate type from the name 28 * @namep: ea name, possibly with type appended 29 * 30 * Returns: GFS2_EATYPE_XXX 31 */ 32 33unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name) 34{ 35 unsigned int type; 36 37 if (strncmp(name, "system.", 7) == 0) { 38 type = GFS2_EATYPE_SYS; 39 if (truncated_name) 40 *truncated_name = name + sizeof("system.") - 1; 41 } else if (strncmp(name, "user.", 5) == 0) { 42 type = GFS2_EATYPE_USR; 43 if (truncated_name) 44 *truncated_name = name + sizeof("user.") - 1; 45 } else if (strncmp(name, "security.", 9) == 0) { 46 type = GFS2_EATYPE_SECURITY; 47 if (truncated_name) 48 *truncated_name = name + sizeof("security.") - 1; 49 } else { 50 type = GFS2_EATYPE_UNUSED; 51 if (truncated_name) 52 *truncated_name = NULL; 53 } 54 55 return type; 56} 57 58static int user_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er) 59{ 60 struct inode *inode = &ip->i_inode; 61 int error = permission(inode, MAY_READ, NULL); 62 if (error) 63 return error; 64 65 return gfs2_ea_get_i(ip, er); 66} 67 68static int user_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er) 69{ 70 struct inode *inode = &ip->i_inode; 71 72 if (S_ISREG(inode->i_mode) || 73 (S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) { 74 int error = permission(inode, MAY_WRITE, NULL); 75 if (error) 76 return error; 77 } else 78 return -EPERM; 79 80 return gfs2_ea_set_i(ip, er); 81} 82 83static int user_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) 84{ 85 struct inode *inode = &ip->i_inode; 86 87 if (S_ISREG(inode->i_mode) || 88 (S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) { 89 int error = permission(inode, MAY_WRITE, NULL); 90 if (error) 91 return error; 92 } else 93 return -EPERM; 94 95 return gfs2_ea_remove_i(ip, er); 96} 97 98static int system_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er) 99{ 100 if (!GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len) && 101 !GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len) && 102 !capable(CAP_SYS_ADMIN)) 103 return -EPERM; 104 105 if (GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl == 0 && 106 (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len) || 107 GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len))) 108 return -EOPNOTSUPP; 109 110 111 112 return gfs2_ea_get_i(ip, er); 113} 114 115static int system_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er) 116{ 117 int remove = 0; 118 int error; 119 120 if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) { 121 if (!(er->er_flags & GFS2_ERF_MODE)) { 122 er->er_mode = ip->i_inode.i_mode; 123 er->er_flags |= GFS2_ERF_MODE; 124 } 125 error = gfs2_acl_validate_set(ip, 1, er, 126 &remove, &er->er_mode); 127 if (error) 128 return error; 129 error = gfs2_ea_set_i(ip, er); 130 if (error) 131 return error; 132 if (remove) 133 gfs2_ea_remove_i(ip, er); 134 return 0; 135 136 } else if (GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) { 137 error = gfs2_acl_validate_set(ip, 0, er, 138 &remove, NULL); 139 if (error) 140 return error; 141 if (!remove) 142 error = gfs2_ea_set_i(ip, er); 143 else { 144 error = gfs2_ea_remove_i(ip, er); 145 if (error == -ENODATA) 146 error = 0; 147 } 148 return error; 149 } 150 151 return -EPERM; 152} 153 154static int system_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) 155{ 156 if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) { 157 int error = gfs2_acl_validate_remove(ip, 1); 158 if (error) 159 return error; 160 161 } else if (GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)) { 162 int error = gfs2_acl_validate_remove(ip, 0); 163 if (error) 164 return error; 165 166 } else 167 return -EPERM; 168 169 return gfs2_ea_remove_i(ip, er); 170} 171 172static int security_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er) 173{ 174 struct inode *inode = &ip->i_inode; 175 int error = permission(inode, MAY_READ, NULL); 176 if (error) 177 return error; 178 179 return gfs2_ea_get_i(ip, er); 180} 181 182static int security_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er) 183{ 184 struct inode *inode = &ip->i_inode; 185 int error = permission(inode, MAY_WRITE, NULL); 186 if (error) 187 return error; 188 189 return gfs2_ea_set_i(ip, er); 190} 191 192static int security_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) 193{ 194 struct inode *inode = &ip->i_inode; 195 int error = permission(inode, MAY_WRITE, NULL); 196 if (error) 197 return error; 198 199 return gfs2_ea_remove_i(ip, er); 200} 201 202static struct gfs2_eattr_operations gfs2_user_eaops = { 203 .eo_get = user_eo_get, 204 .eo_set = user_eo_set, 205 .eo_remove = user_eo_remove, 206 .eo_name = "user", 207}; 208 209struct gfs2_eattr_operations gfs2_system_eaops = { 210 .eo_get = system_eo_get, 211 .eo_set = system_eo_set, 212 .eo_remove = system_eo_remove, 213 .eo_name = "system", 214}; 215 216static struct gfs2_eattr_operations gfs2_security_eaops = { 217 .eo_get = security_eo_get, 218 .eo_set = security_eo_set, 219 .eo_remove = security_eo_remove, 220 .eo_name = "security", 221}; 222 223struct gfs2_eattr_operations *gfs2_ea_ops[] = { 224 NULL, 225 &gfs2_user_eaops, 226 &gfs2_system_eaops, 227 &gfs2_security_eaops, 228}; 229