Blame view

fs/gfs2/acl.c 6.39 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
3
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
9
10
11
12
13
14
   */
  
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
15
  #include <linux/xattr.h>
b3b94faa5   David Teigland   [GFS2] The core o...
16
17
  #include <linux/posix_acl.h>
  #include <linux/posix_acl_xattr.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
18
  #include <linux/gfs2_ondisk.h>
b3b94faa5   David Teigland   [GFS2] The core o...
19
20
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
21
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
22
  #include "acl.h"
307cf6e63   Steven Whitehouse   GFS2: Rename eatt...
23
  #include "xattr.h"
b3b94faa5   David Teigland   [GFS2] The core o...
24
25
26
27
  #include "glock.h"
  #include "inode.h"
  #include "meta_io.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
28
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
29

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
30
  static const char *gfs2_acl_name(int type)
b3b94faa5   David Teigland   [GFS2] The core o...
31
  {
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
32
33
34
35
36
37
38
39
  	switch (type) {
  	case ACL_TYPE_ACCESS:
  		return GFS2_POSIX_ACL_ACCESS;
  	case ACL_TYPE_DEFAULT:
  		return GFS2_POSIX_ACL_DEFAULT;
  	}
  	return NULL;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
40

018a01cd2   Steven Whitehouse   GFS2: We only nee...
41
  struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
42
  {
018a01cd2   Steven Whitehouse   GFS2: We only nee...
43
  	struct gfs2_inode *ip = GFS2_I(inode);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
44
45
46
47
  	struct posix_acl *acl;
  	const char *name;
  	char *data;
  	int len;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
48

3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
49
  	if (!ip->i_eattr)
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
50
  		return NULL;
b3b94faa5   David Teigland   [GFS2] The core o...
51

106381bfb   Steven Whitehouse   GFS2: Add cached ...
52
53
54
  	acl = get_cached_acl(&ip->i_inode, type);
  	if (acl != ACL_NOT_CACHED)
  		return acl;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
55
56
57
  	name = gfs2_acl_name(type);
  	if (name == NULL)
  		return ERR_PTR(-EINVAL);
b3b94faa5   David Teigland   [GFS2] The core o...
58

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
59
60
61
62
63
  	len = gfs2_xattr_acl_get(ip, name, &data);
  	if (len < 0)
  		return ERR_PTR(len);
  	if (len == 0)
  		return NULL;
b3b94faa5   David Teigland   [GFS2] The core o...
64

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
65
66
67
  	acl = posix_acl_from_xattr(data, len);
  	kfree(data);
  	return acl;
b3b94faa5   David Teigland   [GFS2] The core o...
68
  }
d3fb61207   Al Viro   switch posix_acl_...
69
  static int gfs2_set_mode(struct inode *inode, umode_t mode)
b3b94faa5   David Teigland   [GFS2] The core o...
70
  {
69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
71
  	int error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
72

69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
73
74
  	if (mode != inode->i_mode) {
  		struct iattr iattr;
b3b94faa5   David Teigland   [GFS2] The core o...
75

69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
76
77
  		iattr.ia_valid = ATTR_MODE;
  		iattr.ia_mode = mode;
b3b94faa5   David Teigland   [GFS2] The core o...
78

ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
79
  		error = gfs2_setattr_simple(inode, &iattr);
69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
80
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
81

69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
82
  	return error;
b3b94faa5   David Teigland   [GFS2] The core o...
83
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
84
  static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
b3b94faa5   David Teigland   [GFS2] The core o...
85
  {
b3b94faa5   David Teigland   [GFS2] The core o...
86
  	int error;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  	int len;
  	char *data;
  	const char *name = gfs2_acl_name(type);
  
  	BUG_ON(name == NULL);
  	len = posix_acl_to_xattr(acl, NULL, 0);
  	if (len == 0)
  		return 0;
  	data = kmalloc(len, GFP_NOFS);
  	if (data == NULL)
  		return -ENOMEM;
  	error = posix_acl_to_xattr(acl, data, len);
  	if (error < 0)
  		goto out;
431547b3c   Christoph Hellwig   sanitize xattr ha...
101
  	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
102
103
  	if (!error)
  		set_cached_acl(inode, type, acl);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
104
105
106
107
108
109
110
111
  out:
  	kfree(data);
  	return error;
  }
  
  int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
826cae2f2   Al Viro   kill boilerplates...
112
  	struct posix_acl *acl;
d3fb61207   Al Viro   switch posix_acl_...
113
  	umode_t mode = inode->i_mode;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
114
  	int error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
115
116
117
  
  	if (!sdp->sd_args.ar_posix_acl)
  		return 0;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
118
  	if (S_ISLNK(inode->i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
119
  		return 0;
018a01cd2   Steven Whitehouse   GFS2: We only nee...
120
  	acl = gfs2_get_acl(&dip->i_inode, ACL_TYPE_DEFAULT);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
121
122
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
123
  	if (!acl) {
ce3b0f8d5   Al Viro   New helper - curr...
124
  		mode &= ~current_umask();
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
125
126
  		if (mode != inode->i_mode)
  			error = gfs2_set_mode(inode, mode);
b3b94faa5   David Teigland   [GFS2] The core o...
127
128
  		return error;
  	}
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
129
130
131
132
133
  	if (S_ISDIR(inode->i_mode)) {
  		error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
  		if (error)
  			goto out;
  	}
826cae2f2   Al Viro   kill boilerplates...
134
  	error = posix_acl_create(&acl, GFP_NOFS, &mode);
b3b94faa5   David Teigland   [GFS2] The core o...
135
  	if (error < 0)
826cae2f2   Al Viro   kill boilerplates...
136
  		return error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
137
138
  	if (error == 0)
  		goto munge;
b3b94faa5   David Teigland   [GFS2] The core o...
139

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
140
  	error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
141
142
143
  	if (error)
  		goto out;
  munge:
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
144
  	error = gfs2_set_mode(inode, mode);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
145
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
146
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
147
148
149
150
151
  	return error;
  }
  
  int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
  {
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
152
  	struct inode *inode = &ip->i_inode;
bc26ab5f6   Al Viro   kill boilerplate ...
153
  	struct posix_acl *acl;
b3b94faa5   David Teigland   [GFS2] The core o...
154
155
156
  	char *data;
  	unsigned int len;
  	int error;
018a01cd2   Steven Whitehouse   GFS2: We only nee...
157
  	acl = gfs2_get_acl(&ip->i_inode, ACL_TYPE_ACCESS);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
158
159
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
160
  	if (!acl)
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
161
  		return gfs2_setattr_simple(inode, attr);
b3b94faa5   David Teigland   [GFS2] The core o...
162

bc26ab5f6   Al Viro   kill boilerplate ...
163
164
165
166
167
168
  	error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode);
  	if (error)
  		return error;
  
  	len = posix_acl_to_xattr(acl, NULL, 0);
  	data = kmalloc(len, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
169
  	error = -ENOMEM;
bc26ab5f6   Al Viro   kill boilerplate ...
170
  	if (data == NULL)
b3b94faa5   David Teigland   [GFS2] The core o...
171
  		goto out;
bc26ab5f6   Al Viro   kill boilerplate ...
172
173
174
175
  	posix_acl_to_xattr(acl, data, len);
  	error = gfs2_xattr_acl_chmod(ip, attr, data);
  	kfree(data);
  	set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
b3b94faa5   David Teigland   [GFS2] The core o...
176

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
177
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
178
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
179
180
  	return error;
  }
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
181
182
183
184
185
186
187
188
  static int gfs2_acl_type(const char *name)
  {
  	if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
  		return ACL_TYPE_ACCESS;
  	if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
  		return ACL_TYPE_DEFAULT;
  	return -EINVAL;
  }
431547b3c   Christoph Hellwig   sanitize xattr ha...
189
190
  static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
  				 void *buffer, size_t size, int xtype)
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
191
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
192
  	struct inode *inode = dentry->d_inode;
f72f2d2e2   Steven Whitehouse   GFS2: Don't "get"...
193
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
194
  	struct posix_acl *acl;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
195
  	int type;
106381bfb   Steven Whitehouse   GFS2: Add cached ...
196
  	int error;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
197

f72f2d2e2   Steven Whitehouse   GFS2: Don't "get"...
198
199
  	if (!sdp->sd_args.ar_posix_acl)
  		return -EOPNOTSUPP;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
200
201
202
  	type = gfs2_acl_type(name);
  	if (type < 0)
  		return type;
018a01cd2   Steven Whitehouse   GFS2: We only nee...
203
  	acl = gfs2_get_acl(inode, type);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
204
205
206
207
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
  	if (acl == NULL)
  		return -ENODATA;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
208

106381bfb   Steven Whitehouse   GFS2: Add cached ...
209
210
211
212
213
  	error = posix_acl_to_xattr(acl, buffer, size);
  	posix_acl_release(acl);
  
  	return error;
  }
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
214

431547b3c   Christoph Hellwig   sanitize xattr ha...
215
216
217
  static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
  				 const void *value, size_t size, int flags,
  				 int xtype)
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
218
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
219
  	struct inode *inode = dentry->d_inode;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
  	struct posix_acl *acl = NULL;
  	int error = 0, type;
  
  	if (!sdp->sd_args.ar_posix_acl)
  		return -EOPNOTSUPP;
  
  	type = gfs2_acl_type(name);
  	if (type < 0)
  		return type;
  	if (flags & XATTR_CREATE)
  		return -EINVAL;
  	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
  		return value ? -EACCES : 0;
  	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
  		return -EPERM;
  	if (S_ISLNK(inode->i_mode))
  		return -EOPNOTSUPP;
  
  	if (!value)
  		goto set_acl;
  
  	acl = posix_acl_from_xattr(value, size);
  	if (!acl) {
  		/*
  		 * acl_set_file(3) may request that we set default ACLs with
  		 * zero length -- defend (gracefully) against that here.
  		 */
  		goto out;
  	}
  	if (IS_ERR(acl)) {
  		error = PTR_ERR(acl);
  		goto out;
  	}
  
  	error = posix_acl_valid(acl);
  	if (error)
  		goto out_release;
  
  	error = -EINVAL;
  	if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
  		goto out_release;
  
  	if (type == ACL_TYPE_ACCESS) {
d6952123b   Al Viro   switch posix_acl_...
264
  		umode_t mode = inode->i_mode;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  		error = posix_acl_equiv_mode(acl, &mode);
  
  		if (error <= 0) {
  			posix_acl_release(acl);
  			acl = NULL;
  
  			if (error < 0)
  				return error;
  		}
  
  		error = gfs2_set_mode(inode, mode);
  		if (error)
  			goto out_release;
  	}
  
  set_acl:
431547b3c   Christoph Hellwig   sanitize xattr ha...
281
  	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
282
283
284
285
286
287
  	if (!error) {
  		if (acl)
  			set_cached_acl(inode, type, acl);
  		else
  			forget_cached_acl(inode, type);
  	}
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
288
289
290
291
292
  out_release:
  	posix_acl_release(acl);
  out:
  	return error;
  }
b7bb0a129   Stephen Hemminger   gfs: constify xat...
293
  const struct xattr_handler gfs2_xattr_system_handler = {
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
294
  	.prefix = XATTR_SYSTEM_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
295
  	.flags  = GFS2_EATYPE_SYS,
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
296
297
298
  	.get    = gfs2_xattr_system_get,
  	.set    = gfs2_xattr_system_set,
  };