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/sched.h> 11 #include <linux/slab.h> 12 #include <linux/spinlock.h> 13 #include <linux/completion.h> 14 #include <linux/buffer_head.h> 15 #include <linux/xattr.h> 16 #include <linux/posix_acl.h> 17 #include <linux/posix_acl_xattr.h> 18 #include <linux/gfs2_ondisk.h> 19 20 #include "gfs2.h" 21 #include "incore.h" 22 #include "acl.h" 23 #include "xattr.h" 24 #include "glock.h" 25 #include "inode.h" 26 #include "meta_io.h" 27 #include "trans.h" 28 #include "util.h" 29 30 static const char *gfs2_acl_name(int type) 31 { 32 switch (type) { 33 case ACL_TYPE_ACCESS: 34 return GFS2_POSIX_ACL_ACCESS; 35 case ACL_TYPE_DEFAULT: 36 return GFS2_POSIX_ACL_DEFAULT; 37 } 38 return NULL; 39 } 40 41 static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) 42 { 43 struct posix_acl *acl; 44 const char *name; 45 char *data; 46 int len; 47 48 if (!ip->i_eattr) 49 return NULL; 50 51 acl = get_cached_acl(&ip->i_inode, type); 52 if (acl != ACL_NOT_CACHED) 53 return acl; 54 55 name = gfs2_acl_name(type); 56 if (name == NULL) 57 return ERR_PTR(-EINVAL); 58 59 len = gfs2_xattr_acl_get(ip, name, &data); 60 if (len < 0) 61 return ERR_PTR(len); 62 if (len == 0) 63 return NULL; 64 65 acl = posix_acl_from_xattr(data, len); 66 kfree(data); 67 return acl; 68 } 69 70 /** 71 * gfs2_check_acl - Check an ACL to see if we're allowed to do something 72 * @inode: the file we want to do something to 73 * @mask: what we want to do 74 * 75 * Returns: errno 76 */ 77 78 int gfs2_check_acl(struct inode *inode, int mask) 79 { 80 struct posix_acl *acl; 81 int error; 82 83 acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); 84 if (IS_ERR(acl)) 85 return PTR_ERR(acl); 86 87 if (acl) { 88 error = posix_acl_permission(inode, acl, mask); 89 posix_acl_release(acl); 90 return error; 91 } 92 93 return -EAGAIN; 94 } 95 96 static int gfs2_set_mode(struct inode *inode, mode_t mode) 97 { 98 int error = 0; 99 100 if (mode != inode->i_mode) { 101 struct iattr iattr; 102 103 iattr.ia_valid = ATTR_MODE; 104 iattr.ia_mode = mode; 105 106 error = gfs2_setattr_simple(GFS2_I(inode), &iattr); 107 } 108 109 return error; 110 } 111 112 static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) 113 { 114 int error; 115 int len; 116 char *data; 117 const char *name = gfs2_acl_name(type); 118 119 BUG_ON(name == NULL); 120 len = posix_acl_to_xattr(acl, NULL, 0); 121 if (len == 0) 122 return 0; 123 data = kmalloc(len, GFP_NOFS); 124 if (data == NULL) 125 return -ENOMEM; 126 error = posix_acl_to_xattr(acl, data, len); 127 if (error < 0) 128 goto out; 129 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 130 if (!error) 131 set_cached_acl(inode, type, acl); 132 out: 133 kfree(data); 134 return error; 135 } 136 137 int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode) 138 { 139 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 140 struct posix_acl *acl, *clone; 141 mode_t mode = inode->i_mode; 142 int error = 0; 143 144 if (!sdp->sd_args.ar_posix_acl) 145 return 0; 146 if (S_ISLNK(inode->i_mode)) 147 return 0; 148 149 acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); 150 if (IS_ERR(acl)) 151 return PTR_ERR(acl); 152 if (!acl) { 153 mode &= ~current_umask(); 154 if (mode != inode->i_mode) 155 error = gfs2_set_mode(inode, mode); 156 return error; 157 } 158 159 if (S_ISDIR(inode->i_mode)) { 160 error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); 161 if (error) 162 goto out; 163 } 164 165 clone = posix_acl_clone(acl, GFP_NOFS); 166 error = -ENOMEM; 167 if (!clone) 168 goto out; 169 posix_acl_release(acl); 170 acl = clone; 171 172 error = posix_acl_create_masq(acl, &mode); 173 if (error < 0) 174 goto out; 175 if (error == 0) 176 goto munge; 177 178 error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); 179 if (error) 180 goto out; 181 munge: 182 error = gfs2_set_mode(inode, mode); 183 out: 184 posix_acl_release(acl); 185 return error; 186 } 187 188 int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) 189 { 190 struct posix_acl *acl, *clone; 191 char *data; 192 unsigned int len; 193 int error; 194 195 acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); 196 if (IS_ERR(acl)) 197 return PTR_ERR(acl); 198 if (!acl) 199 return gfs2_setattr_simple(ip, attr); 200 201 clone = posix_acl_clone(acl, GFP_NOFS); 202 error = -ENOMEM; 203 if (!clone) 204 goto out; 205 posix_acl_release(acl); 206 acl = clone; 207 208 error = posix_acl_chmod_masq(acl, attr->ia_mode); 209 if (!error) { 210 len = posix_acl_to_xattr(acl, NULL, 0); 211 data = kmalloc(len, GFP_NOFS); 212 error = -ENOMEM; 213 if (data == NULL) 214 goto out; 215 posix_acl_to_xattr(acl, data, len); 216 error = gfs2_xattr_acl_chmod(ip, attr, data); 217 kfree(data); 218 set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl); 219 } 220 221 out: 222 posix_acl_release(acl); 223 return error; 224 } 225 226 static int gfs2_acl_type(const char *name) 227 { 228 if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) 229 return ACL_TYPE_ACCESS; 230 if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) 231 return ACL_TYPE_DEFAULT; 232 return -EINVAL; 233 } 234 235 static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, 236 void *buffer, size_t size, int xtype) 237 { 238 struct inode *inode = dentry->d_inode; 239 struct posix_acl *acl; 240 int type; 241 int error; 242 243 type = gfs2_acl_type(name); 244 if (type < 0) 245 return type; 246 247 acl = gfs2_acl_get(GFS2_I(inode), type); 248 if (IS_ERR(acl)) 249 return PTR_ERR(acl); 250 if (acl == NULL) 251 return -ENODATA; 252 253 error = posix_acl_to_xattr(acl, buffer, size); 254 posix_acl_release(acl); 255 256 return error; 257 } 258 259 static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, 260 const void *value, size_t size, int flags, 261 int xtype) 262 { 263 struct inode *inode = dentry->d_inode; 264 struct gfs2_sbd *sdp = GFS2_SB(inode); 265 struct posix_acl *acl = NULL; 266 int error = 0, type; 267 268 if (!sdp->sd_args.ar_posix_acl) 269 return -EOPNOTSUPP; 270 271 type = gfs2_acl_type(name); 272 if (type < 0) 273 return type; 274 if (flags & XATTR_CREATE) 275 return -EINVAL; 276 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 277 return value ? -EACCES : 0; 278 if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) 279 return -EPERM; 280 if (S_ISLNK(inode->i_mode)) 281 return -EOPNOTSUPP; 282 283 if (!value) 284 goto set_acl; 285 286 acl = posix_acl_from_xattr(value, size); 287 if (!acl) { 288 /* 289 * acl_set_file(3) may request that we set default ACLs with 290 * zero length -- defend (gracefully) against that here. 291 */ 292 goto out; 293 } 294 if (IS_ERR(acl)) { 295 error = PTR_ERR(acl); 296 goto out; 297 } 298 299 error = posix_acl_valid(acl); 300 if (error) 301 goto out_release; 302 303 error = -EINVAL; 304 if (acl->a_count > GFS2_ACL_MAX_ENTRIES) 305 goto out_release; 306 307 if (type == ACL_TYPE_ACCESS) { 308 mode_t mode = inode->i_mode; 309 error = posix_acl_equiv_mode(acl, &mode); 310 311 if (error <= 0) { 312 posix_acl_release(acl); 313 acl = NULL; 314 315 if (error < 0) 316 return error; 317 } 318 319 error = gfs2_set_mode(inode, mode); 320 if (error) 321 goto out_release; 322 } 323 324 set_acl: 325 error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); 326 if (!error) { 327 if (acl) 328 set_cached_acl(inode, type, acl); 329 else 330 forget_cached_acl(inode, type); 331 } 332 out_release: 333 posix_acl_release(acl); 334 out: 335 return error; 336 } 337 338 struct xattr_handler gfs2_xattr_system_handler = { 339 .prefix = XATTR_SYSTEM_PREFIX, 340 .flags = GFS2_EATYPE_SYS, 341 .get = gfs2_xattr_system_get, 342 .set = gfs2_xattr_system_set, 343 }; 344 345