Merge with Linux 2.5.74.
[linux-2.6/linux-mips.git] / fs / xfs / xfs_cap.c
blob61731d7573a43dad0de3f58a0efd3b21c51aada0
1 /*
2 * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
26 * http://www.sgi.com
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #include "xfs.h"
35 STATIC int xfs_cap_allow_set(vnode_t *);
39 * Test for existence of capability attribute as efficiently as possible.
41 int
42 xfs_cap_vhascap(
43 vnode_t *vp)
45 int error;
46 int len = sizeof(xfs_cap_set_t);
47 int flags = ATTR_KERNOVAL|ATTR_ROOT;
49 VOP_ATTR_GET(vp, SGI_CAP_LINUX, NULL, &len, flags, sys_cred, error);
50 return (error == 0);
54 * Convert from extended attribute representation to in-memory for XFS.
56 STATIC int
57 posix_cap_xattr_to_xfs(
58 posix_cap_xattr *src,
59 size_t size,
60 xfs_cap_set_t *dest)
62 if (!src || !dest)
63 return EINVAL;
65 if (src->c_version != cpu_to_le32(POSIX_CAP_XATTR_VERSION))
66 return EINVAL;
67 if (src->c_abiversion != cpu_to_le32(_LINUX_CAPABILITY_VERSION))
68 return EINVAL;
70 if (size < sizeof(posix_cap_xattr))
71 return EINVAL;
73 ASSERT(sizeof(dest->cap_effective) == sizeof(src->c_effective));
75 dest->cap_effective = src->c_effective;
76 dest->cap_permitted = src->c_permitted;
77 dest->cap_inheritable = src->c_inheritable;
79 return 0;
83 * Convert from in-memory XFS to extended attribute representation.
85 STATIC int
86 posix_cap_xfs_to_xattr(
87 xfs_cap_set_t *src,
88 posix_cap_xattr *xattr_cap,
89 size_t size)
91 size_t new_size = posix_cap_xattr_size();
93 if (size < new_size)
94 return -ERANGE;
96 ASSERT(sizeof(xattr_cap->c_effective) == sizeof(src->cap_effective));
98 xattr_cap->c_version = cpu_to_le32(POSIX_CAP_XATTR_VERSION);
99 xattr_cap->c_abiversion = cpu_to_le32(_LINUX_CAPABILITY_VERSION);
100 xattr_cap->c_effective = src->cap_effective;
101 xattr_cap->c_permitted = src->cap_permitted;
102 xattr_cap->c_inheritable= src->cap_inheritable;
104 return new_size;
108 xfs_cap_vget(
109 vnode_t *vp,
110 void *cap,
111 size_t size)
113 int error;
114 int len = sizeof(xfs_cap_set_t);
115 int flags = ATTR_ROOT;
116 xfs_cap_set_t xfs_cap = { 0 };
117 posix_cap_xattr *xattr_cap = cap;
118 char *data = (char *)&xfs_cap;
120 VN_HOLD(vp);
121 if ((error = _MAC_VACCESS(vp, NULL, VREAD)))
122 goto out;
124 if (!size) {
125 flags |= ATTR_KERNOVAL;
126 data = NULL;
128 VOP_ATTR_GET(vp, SGI_CAP_LINUX, data, &len, flags, sys_cred, error);
129 if (error)
130 goto out;
131 ASSERT(len == sizeof(xfs_cap_set_t));
133 error = (size)? -posix_cap_xattr_size() :
134 -posix_cap_xfs_to_xattr(&xfs_cap, xattr_cap, size);
135 out:
136 VN_RELE(vp);
137 return -error;
141 xfs_cap_vremove(
142 vnode_t *vp)
144 int error;
146 VN_HOLD(vp);
147 error = xfs_cap_allow_set(vp);
148 if (!error) {
149 VOP_ATTR_REMOVE(vp, SGI_CAP_LINUX, ATTR_ROOT, sys_cred, error);
150 if (error == ENOATTR)
151 error = 0; /* 'scool */
153 VN_RELE(vp);
154 return -error;
158 xfs_cap_vset(
159 vnode_t *vp,
160 void *cap,
161 size_t size)
163 posix_cap_xattr *xattr_cap = cap;
164 xfs_cap_set_t xfs_cap;
165 int error;
167 if (!cap)
168 return -EINVAL;
170 error = posix_cap_xattr_to_xfs(xattr_cap, size, &xfs_cap);
171 if (error)
172 return -error;
174 VN_HOLD(vp);
175 error = xfs_cap_allow_set(vp);
176 if (error)
177 goto out;
179 VOP_ATTR_SET(vp, SGI_CAP_LINUX, (char *)&xfs_cap,
180 sizeof(xfs_cap_set_t), ATTR_ROOT, sys_cred, error);
181 out:
182 VN_RELE(vp);
183 return -error;
186 STATIC int
187 xfs_cap_allow_set(
188 vnode_t *vp)
190 vattr_t va;
191 int error;
193 if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
194 return EROFS;
195 if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
196 return error;
197 va.va_mask = XFS_AT_UID;
198 VOP_GETATTR(vp, &va, 0, NULL, error);
199 if (error)
200 return error;
201 if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
202 return EPERM;
203 return error;