* Set attributes */
| 1236 | * Set attributes |
| 1237 | */ |
| 1238 | static int |
| 1239 | mqfs_setattr(struct vop_setattr_args *ap) |
| 1240 | { |
| 1241 | struct mqfs_node *pn; |
| 1242 | struct vattr *vap; |
| 1243 | struct vnode *vp; |
| 1244 | struct thread *td; |
| 1245 | int c, error; |
| 1246 | uid_t uid; |
| 1247 | gid_t gid; |
| 1248 | |
| 1249 | td = curthread; |
| 1250 | vap = ap->a_vap; |
| 1251 | vp = ap->a_vp; |
| 1252 | if ((vap->va_type != VNON) || |
| 1253 | (vap->va_nlink != VNOVAL) || |
| 1254 | (vap->va_fsid != VNOVAL) || |
| 1255 | (vap->va_fileid != VNOVAL) || |
| 1256 | (vap->va_blocksize != VNOVAL) || |
| 1257 | (vap->va_flags != VNOVAL && vap->va_flags != 0) || |
| 1258 | (vap->va_rdev != VNOVAL) || |
| 1259 | ((int)vap->va_bytes != VNOVAL) || |
| 1260 | (vap->va_gen != VNOVAL)) { |
| 1261 | return (EINVAL); |
| 1262 | } |
| 1263 | |
| 1264 | pn = VTON(vp); |
| 1265 | |
| 1266 | error = c = 0; |
| 1267 | if (vap->va_uid == (uid_t)VNOVAL) |
| 1268 | uid = pn->mn_uid; |
| 1269 | else |
| 1270 | uid = vap->va_uid; |
| 1271 | if (vap->va_gid == (gid_t)VNOVAL) |
| 1272 | gid = pn->mn_gid; |
| 1273 | else |
| 1274 | gid = vap->va_gid; |
| 1275 | |
| 1276 | if (uid != pn->mn_uid || gid != pn->mn_gid) { |
| 1277 | /* |
| 1278 | * To modify the ownership of a file, must possess VADMIN |
| 1279 | * for that file. |
| 1280 | */ |
| 1281 | if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, td))) |
| 1282 | return (error); |
| 1283 | |
| 1284 | /* |
| 1285 | * XXXRW: Why is there a privilege check here: shouldn't the |
| 1286 | * check in VOP_ACCESS() be enough? Also, are the group bits |
| 1287 | * below definitely right? |
| 1288 | */ |
| 1289 | if (((ap->a_cred->cr_uid != pn->mn_uid) || uid != pn->mn_uid || |
| 1290 | (gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) && |
| 1291 | (error = priv_check(td, PRIV_MQ_ADMIN)) != 0) |
| 1292 | return (error); |
| 1293 | pn->mn_uid = uid; |
| 1294 | pn->mn_gid = gid; |
| 1295 | c = 1; |
nothing calls this directly
no test coverage detected