| 1283 | #endif /* COMPAT_FREEBSD11 */ |
| 1284 | |
| 1285 | int |
| 1286 | kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, |
| 1287 | int mode, dev_t dev) |
| 1288 | { |
| 1289 | struct vnode *vp; |
| 1290 | struct mount *mp; |
| 1291 | struct vattr vattr; |
| 1292 | struct nameidata nd; |
| 1293 | int error, whiteout = 0; |
| 1294 | |
| 1295 | AUDIT_ARG_MODE(mode); |
| 1296 | AUDIT_ARG_DEV(dev); |
| 1297 | switch (mode & S_IFMT) { |
| 1298 | case S_IFCHR: |
| 1299 | case S_IFBLK: |
| 1300 | error = priv_check(td, PRIV_VFS_MKNOD_DEV); |
| 1301 | if (error == 0 && dev == VNOVAL) |
| 1302 | error = EINVAL; |
| 1303 | break; |
| 1304 | case S_IFWHT: |
| 1305 | error = priv_check(td, PRIV_VFS_MKNOD_WHT); |
| 1306 | break; |
| 1307 | case S_IFIFO: |
| 1308 | if (dev == 0) |
| 1309 | return (kern_mkfifoat(td, fd, path, pathseg, mode)); |
| 1310 | /* FALLTHROUGH */ |
| 1311 | default: |
| 1312 | error = EINVAL; |
| 1313 | break; |
| 1314 | } |
| 1315 | if (error != 0) |
| 1316 | return (error); |
| 1317 | restart: |
| 1318 | bwillwrite(); |
| 1319 | NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 | |
| 1320 | NOCACHE, pathseg, path, fd, &cap_mknodat_rights, |
| 1321 | td); |
| 1322 | if ((error = namei(&nd)) != 0) |
| 1323 | return (error); |
| 1324 | vp = nd.ni_vp; |
| 1325 | if (vp != NULL) { |
| 1326 | NDFREE(&nd, NDF_ONLY_PNBUF); |
| 1327 | if (vp == nd.ni_dvp) |
| 1328 | vrele(nd.ni_dvp); |
| 1329 | else |
| 1330 | vput(nd.ni_dvp); |
| 1331 | vrele(vp); |
| 1332 | return (EEXIST); |
| 1333 | } else { |
| 1334 | VATTR_NULL(&vattr); |
| 1335 | vattr.va_mode = (mode & ALLPERMS) & |
| 1336 | ~td->td_proc->p_pd->pd_cmask; |
| 1337 | vattr.va_rdev = dev; |
| 1338 | whiteout = 0; |
| 1339 | |
| 1340 | switch (mode & S_IFMT) { |
| 1341 | case S_IFCHR: |
| 1342 | vattr.va_type = VCHR; |
no test coverage detected