Blame view

fs/gfs2/acl.c 6.42 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

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
41
42
43
44
45
46
  static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
  {
  	struct posix_acl *acl;
  	const char *name;
  	char *data;
  	int len;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
47

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

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

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
58
59
60
61
62
  	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...
63

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
64
65
66
  	acl = posix_acl_from_xattr(data, len);
  	kfree(data);
  	return acl;
b3b94faa5   David Teigland   [GFS2] The core o...
67
  }
4e34e719e   Christoph Hellwig   fs: take the ACL ...
68
  struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
b3b94faa5   David Teigland   [GFS2] The core o...
69
  {
4e34e719e   Christoph Hellwig   fs: take the ACL ...
70
  	return gfs2_acl_get(GFS2_I(inode), type);
b3b94faa5   David Teigland   [GFS2] The core o...
71
  }
d3fb61207   Al Viro   switch posix_acl_...
72
  static int gfs2_set_mode(struct inode *inode, umode_t mode)
b3b94faa5   David Teigland   [GFS2] The core o...
73
  {
69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
74
  	int error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
75

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

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

69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
82
83
  		error = gfs2_setattr_simple(GFS2_I(inode), &iattr);
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
84

69dca4246   Steven Whitehouse   GFS2: Use gfs2_se...
85
  	return error;
b3b94faa5   David Teigland   [GFS2] The core o...
86
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
87
  static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
b3b94faa5   David Teigland   [GFS2] The core o...
88
  {
b3b94faa5   David Teigland   [GFS2] The core o...
89
  	int error;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  	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...
104
  	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
105
106
  	if (!error)
  		set_cached_acl(inode, type, acl);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
107
108
109
110
111
112
113
114
  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...
115
  	struct posix_acl *acl;
d3fb61207   Al Viro   switch posix_acl_...
116
  	umode_t mode = inode->i_mode;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
117
  	int error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
118
119
120
  
  	if (!sdp->sd_args.ar_posix_acl)
  		return 0;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
121
  	if (S_ISLNK(inode->i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
122
  		return 0;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
123
124
125
  	acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT);
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
126
  	if (!acl) {
ce3b0f8d5   Al Viro   New helper - curr...
127
  		mode &= ~current_umask();
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
128
129
  		if (mode != inode->i_mode)
  			error = gfs2_set_mode(inode, mode);
b3b94faa5   David Teigland   [GFS2] The core o...
130
131
  		return error;
  	}
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
132
133
134
135
136
  	if (S_ISDIR(inode->i_mode)) {
  		error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
  		if (error)
  			goto out;
  	}
826cae2f2   Al Viro   kill boilerplates...
137
  	error = posix_acl_create(&acl, GFP_NOFS, &mode);
b3b94faa5   David Teigland   [GFS2] The core o...
138
  	if (error < 0)
826cae2f2   Al Viro   kill boilerplates...
139
  		return error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
140
141
  	if (error == 0)
  		goto munge;
b3b94faa5   David Teigland   [GFS2] The core o...
142

479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
143
  	error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
144
145
146
  	if (error)
  		goto out;
  munge:
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
147
  	error = gfs2_set_mode(inode, mode);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
148
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
149
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
150
151
152
153
154
  	return error;
  }
  
  int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
  {
bc26ab5f6   Al Viro   kill boilerplate ...
155
  	struct posix_acl *acl;
b3b94faa5   David Teigland   [GFS2] The core o...
156
157
158
  	char *data;
  	unsigned int len;
  	int error;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
159
160
161
  	acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
162
163
  	if (!acl)
  		return gfs2_setattr_simple(ip, attr);
bc26ab5f6   Al Viro   kill boilerplate ...
164
165
166
167
168
169
  	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...
170
  	error = -ENOMEM;
bc26ab5f6   Al Viro   kill boilerplate ...
171
  	if (data == NULL)
b3b94faa5   David Teigland   [GFS2] The core o...
172
  		goto out;
bc26ab5f6   Al Viro   kill boilerplate ...
173
174
175
176
  	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...
177

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
178
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
179
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
180
181
  	return error;
  }
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
182
183
184
185
186
187
188
189
  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...
190
191
  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...
192
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
193
  	struct inode *inode = dentry->d_inode;
f72f2d2e2   Steven Whitehouse   GFS2: Don't "get"...
194
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
195
  	struct posix_acl *acl;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
196
  	int type;
106381bfb   Steven Whitehouse   GFS2: Add cached ...
197
  	int error;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
198

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

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

431547b3c   Christoph Hellwig   sanitize xattr ha...
216
217
218
  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...
219
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
220
  	struct inode *inode = dentry->d_inode;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
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
264
  	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_...
265
  		umode_t mode = inode->i_mode;
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  		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...
282
  	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
106381bfb   Steven Whitehouse   GFS2: Add cached ...
283
284
285
286
287
288
  	if (!error) {
  		if (acl)
  			set_cached_acl(inode, type, acl);
  		else
  			forget_cached_acl(inode, type);
  	}
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
289
290
291
292
293
  out_release:
  	posix_acl_release(acl);
  out:
  	return error;
  }
b7bb0a129   Stephen Hemminger   gfs: constify xat...
294
  const struct xattr_handler gfs2_xattr_system_handler = {
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
295
  	.prefix = XATTR_SYSTEM_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
296
  	.flags  = GFS2_EATYPE_SYS,
2646a1f61   Steven Whitehouse   GFS2: Fix up syst...
297
298
299
  	.get    = gfs2_xattr_system_get,
  	.set    = gfs2_xattr_system_set,
  };