Blame view

fs/gfs2/acl.c 5.54 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
15
16
   */
  
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
  #include <linux/posix_acl.h>
  #include <linux/posix_acl_xattr.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
17
  #include <linux/gfs2_ondisk.h>
b3b94faa5   David Teigland   [GFS2] The core o...
18
19
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
20
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
21
  #include "acl.h"
307cf6e63   Steven Whitehouse   GFS2: Rename eatt...
22
  #include "xattr.h"
b3b94faa5   David Teigland   [GFS2] The core o...
23
24
25
26
  #include "glock.h"
  #include "inode.h"
  #include "meta_io.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
27
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
28
29
30
31
32
  
  #define ACL_ACCESS 1
  #define ACL_DEFAULT 0
  
  int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
40b78a322   Steven Whitehouse   GFS2: Clean up of...
33
  			  struct gfs2_ea_request *er, int *remove, mode_t *mode)
b3b94faa5   David Teigland   [GFS2] The core o...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  {
  	struct posix_acl *acl;
  	int error;
  
  	error = gfs2_acl_validate_remove(ip, access);
  	if (error)
  		return error;
  
  	if (!er->er_data)
  		return -EINVAL;
  
  	acl = posix_acl_from_xattr(er->er_data, er->er_data_len);
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
  	if (!acl) {
  		*remove = 1;
  		return 0;
  	}
  
  	error = posix_acl_valid(acl);
  	if (error)
  		goto out;
  
  	if (access) {
  		error = posix_acl_equiv_mode(acl, mode);
  		if (!error)
  			*remove = 1;
  		else if (error > 0)
  			error = 0;
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
64
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
65
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
66
67
68
69
70
  	return error;
  }
  
  int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
71
  	if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
b3b94faa5   David Teigland   [GFS2] The core o...
72
  		return -EOPNOTSUPP;
3bd858ab1   Satyam Sharma   Introduce is_owne...
73
  	if (!is_owner_or_cap(&ip->i_inode))
b3b94faa5   David Teigland   [GFS2] The core o...
74
  		return -EPERM;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
75
  	if (S_ISLNK(ip->i_inode.i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
76
  		return -EOPNOTSUPP;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
77
  	if (!access && !S_ISDIR(ip->i_inode.i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
78
79
80
81
  		return -EACCES;
  
  	return 0;
  }
40b78a322   Steven Whitehouse   GFS2: Clean up of...
82
83
84
  static int acl_get(struct gfs2_inode *ip, const char *name,
  		   struct posix_acl **acl, struct gfs2_ea_location *el,
  		   char **datap, unsigned int *lenp)
b3b94faa5   David Teigland   [GFS2] The core o...
85
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
86
87
  	char *data;
  	unsigned int len;
b3b94faa5   David Teigland   [GFS2] The core o...
88
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
89
  	el->el_bh = NULL;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
90
  	if (!ip->i_eattr)
b3b94faa5   David Teigland   [GFS2] The core o...
91
  		return 0;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
92
  	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, el);
b3b94faa5   David Teigland   [GFS2] The core o...
93
94
95
96
97
98
  	if (error)
  		return error;
  	if (!el->el_ea)
  		return 0;
  	if (!GFS2_EA_DATA_LEN(el->el_ea))
  		goto out;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
99
100
  	len = GFS2_EA_DATA_LEN(el->el_ea);
  	data = kmalloc(len, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
101
  	error = -ENOMEM;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
102
  	if (!data)
b3b94faa5   David Teigland   [GFS2] The core o...
103
  		goto out;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
104
105
  	error = gfs2_ea_get_copy(ip, el, data, len);
  	if (error < 0)
b3b94faa5   David Teigland   [GFS2] The core o...
106
  		goto out_kfree;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
107
  	error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
108
109
  
  	if (acl) {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
110
  		*acl = posix_acl_from_xattr(data, len);
b3b94faa5   David Teigland   [GFS2] The core o...
111
112
113
  		if (IS_ERR(*acl))
  			error = PTR_ERR(*acl);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
114
  out_kfree:
40b78a322   Steven Whitehouse   GFS2: Clean up of...
115
116
117
118
119
  	if (error || !datap) {
  		kfree(data);
  	} else {
  		*datap = data;
  		*lenp = len;
b3b94faa5   David Teigland   [GFS2] The core o...
120
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
121
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
122
123
124
125
  	return error;
  }
  
  /**
77386e1f6   Steven Whitehouse   [GFS2] Remove gfs...
126
   * gfs2_check_acl - Check an ACL to see if we're allowed to do something
b3b94faa5   David Teigland   [GFS2] The core o...
127
128
129
130
131
   * @inode: the file we want to do something to
   * @mask: what we want to do
   *
   * Returns: errno
   */
77386e1f6   Steven Whitehouse   [GFS2] Remove gfs...
132
  int gfs2_check_acl(struct inode *inode, int mask)
b3b94faa5   David Teigland   [GFS2] The core o...
133
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
134
  	struct gfs2_ea_location el;
b3b94faa5   David Teigland   [GFS2] The core o...
135
136
  	struct posix_acl *acl = NULL;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
137
138
  	error = acl_get(GFS2_I(inode), GFS2_POSIX_ACL_ACCESS, &acl, &el, NULL, NULL);
  	brelse(el.el_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
139
140
141
142
143
144
145
146
147
148
149
  	if (error)
  		return error;
  
  	if (acl) {
  		error = posix_acl_permission(inode, acl, mask);
  		posix_acl_release(acl);
  		return error;
  	}
  
  	return -EAGAIN;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
150
151
  static int munge_mode(struct gfs2_inode *ip, mode_t mode)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
152
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
153
154
155
156
157
158
159
160
161
162
  	struct buffer_head *dibh;
  	int error;
  
  	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
  	if (error)
  		return error;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
  		gfs2_assert_withdraw(sdp,
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
163
164
  				(ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT));
  		ip->i_inode.i_mode = mode;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
165
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
166
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
167
168
169
170
171
172
173
174
175
176
  		brelse(dibh);
  	}
  
  	gfs2_trans_end(sdp);
  
  	return 0;
  }
  
  int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
177
  	struct gfs2_ea_location el;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
178
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
179
  	struct posix_acl *acl = NULL, *clone;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
180
  	mode_t mode = ip->i_inode.i_mode;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
181
182
  	char *data = NULL;
  	unsigned int len;
b3b94faa5   David Teigland   [GFS2] The core o...
183
184
185
186
  	int error;
  
  	if (!sdp->sd_args.ar_posix_acl)
  		return 0;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
187
  	if (S_ISLNK(ip->i_inode.i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
188
  		return 0;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
189
190
  	error = acl_get(dip, GFS2_POSIX_ACL_DEFAULT, &acl, &el, &data, &len);
  	brelse(el.el_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
191
192
193
  	if (error)
  		return error;
  	if (!acl) {
ce3b0f8d5   Al Viro   New helper - curr...
194
  		mode &= ~current_umask();
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
195
  		if (mode != ip->i_inode.i_mode)
b3b94faa5   David Teigland   [GFS2] The core o...
196
197
198
  			error = munge_mode(ip, mode);
  		return error;
  	}
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
199
  	clone = posix_acl_clone(acl, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
200
201
202
203
204
  	error = -ENOMEM;
  	if (!clone)
  		goto out;
  	posix_acl_release(acl);
  	acl = clone;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
205
  	if (S_ISDIR(ip->i_inode.i_mode)) {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
206
207
  		error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS,
  				       GFS2_POSIX_ACL_DEFAULT, data, len, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
208
209
210
211
212
213
214
  		if (error)
  			goto out;
  	}
  
  	error = posix_acl_create_masq(acl, &mode);
  	if (error < 0)
  		goto out;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
215
216
  	if (error == 0)
  		goto munge;
b3b94faa5   David Teigland   [GFS2] The core o...
217

40b78a322   Steven Whitehouse   GFS2: Clean up of...
218
219
220
221
222
223
224
  	posix_acl_to_xattr(acl, data, len);
  	error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS,
  			       GFS2_POSIX_ACL_ACCESS, data, len, 0);
  	if (error)
  		goto out;
  munge:
  	error = munge_mode(ip, mode);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
225
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
226
  	posix_acl_release(acl);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
227
  	kfree(data);
b3b94faa5   David Teigland   [GFS2] The core o...
228
229
230
231
232
233
234
235
236
237
  	return error;
  }
  
  int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
  {
  	struct posix_acl *acl = NULL, *clone;
  	struct gfs2_ea_location el;
  	char *data;
  	unsigned int len;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
238
  	error = acl_get(ip, GFS2_POSIX_ACL_ACCESS, &acl, &el, &data, &len);
b3b94faa5   David Teigland   [GFS2] The core o...
239
  	if (error)
40b78a322   Steven Whitehouse   GFS2: Clean up of...
240
  		goto out_brelse;
b3b94faa5   David Teigland   [GFS2] The core o...
241
242
  	if (!acl)
  		return gfs2_setattr_simple(ip, attr);
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
243
  	clone = posix_acl_clone(acl, GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
244
245
246
247
248
249
250
251
252
253
254
  	error = -ENOMEM;
  	if (!clone)
  		goto out;
  	posix_acl_release(acl);
  	acl = clone;
  
  	error = posix_acl_chmod_masq(acl, attr->ia_mode);
  	if (!error) {
  		posix_acl_to_xattr(acl, data, len);
  		error = gfs2_ea_acl_chmod(ip, &el, attr, data);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
255
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
256
  	posix_acl_release(acl);
b3b94faa5   David Teigland   [GFS2] The core o...
257
  	kfree(data);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
258
259
  out_brelse:
  	brelse(el.el_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
260
261
  	return error;
  }