From 6cb92a3c9e9a3bfd60629a34e900e1c88285e838 Mon Sep 17 00:00:00 2001 From: guenther Date: Mon, 25 Mar 2024 17:57:07 +0000 Subject: [PATCH] Move the "no (hard) linking directories" and "no cross-mount links" checks from all the filesystems that support hardlinks at all into the VFS layer. Simplify, EPERM description in link(2). ok miod@ mpi@ --- lib/libc/sys/link.2 | 10 +++------- sys/kern/vfs_syscalls.c | 18 +++++++++++++----- sys/miscfs/fuse/fuse_vnops.c | 12 +----------- sys/nfs/nfs_serv.c | 4 ++-- sys/nfs/nfs_vnops.c | 7 +------ sys/tmpfs/tmpfs_vnops.c | 15 +-------------- sys/ufs/ext2fs/ext2fs_vnops.c | 12 +----------- sys/ufs/ufs/ufs_vnops.c | 12 +----------- 8 files changed, 23 insertions(+), 67 deletions(-) diff --git a/lib/libc/sys/link.2 b/lib/libc/sys/link.2 index a9c241a5583..4d6f9f1abe3 100644 --- a/lib/libc/sys/link.2 +++ b/lib/libc/sys/link.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: link.2,v 1.29 2015/09/10 17:55:21 schwarze Exp $ +.\" $OpenBSD: link.2,v 1.30 2024/03/25 17:57:07 guenther Exp $ .\" $NetBSD: link.2,v 1.7 1995/02/27 12:34:01 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)link.2 8.3 (Berkeley) 1/12/94 .\" -.Dd $Mdocdate: September 10 2015 $ +.Dd $Mdocdate: March 25 2024 $ .Dt LINK 2 .Os .Sh NAME @@ -172,11 +172,7 @@ does exist. .It Bq Er EPERM The file named by .Fa name1 -is a directory and the effective -user ID is not superuser, -or the file system containing the file does not permit the use of -.Fn link -on a directory. +is a directory. .It Bq Er EPERM The file named by .Fa name1 diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 6eb0796ce00..40445f251bf 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.363 2024/02/03 18:51:58 beck Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.364 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -1703,7 +1703,6 @@ dolinkat(struct proc *p, int fd1, const char *path1, int fd2, struct vnode *vp; struct nameidata nd; int error, follow; - int flags; if (flag & ~AT_SYMLINK_FOLLOW) return (EINVAL); @@ -1716,12 +1715,12 @@ dolinkat(struct proc *p, int fd1, const char *path1, int fd2, return (error); vp = nd.ni_vp; - flags = LOCKPARENT; if (vp->v_type == VDIR) { - flags |= STRIPSLASHES; + error = EPERM; + goto out; } - NDINITAT(&nd, CREATE, flags, UIO_USERSPACE, fd2, path2, p); + NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd2, path2, p); nd.ni_pledge = PLEDGE_CPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) @@ -1736,6 +1735,15 @@ dolinkat(struct proc *p, int fd1, const char *path1, int fd2, error = EEXIST; goto out; } + + /* No cross-mount links! */ + if (nd.ni_dvp->v_mount != vp->v_mount) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + vput(nd.ni_dvp); + error = EXDEV; + goto out; + } + error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); out: vrele(vp); diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index c3c06c8775d..173d70562f6 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.67 2023/09/08 20:00:28 mvs Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.68 2024/03/25 17:57:07 guenther Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -646,16 +646,6 @@ fusefs_link(void *v) error = ENOSYS; goto out2; } - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - error = EPERM; - goto out2; - } - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - error = EXDEV; - goto out2; - } if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { VOP_ABORTOP(dvp, cnp); goto out2; diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c index 421c4025696..2f4624cbafe 100644 --- a/sys/nfs/nfs_serv.c +++ b/sys/nfs/nfs_serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_serv.c,v 1.122 2023/03/08 04:43:09 guenther Exp $ */ +/* $OpenBSD: nfs_serv.c,v 1.123 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: nfs_serv.c,v 1.34 1997/05/12 23:37:12 fvdl Exp $ */ /* @@ -1598,7 +1598,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } - if (vp->v_type == VDIR && (error = suser_ucred(cred)) != 0) + if (vp->v_type == VDIR) goto out1; NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, NULL, procp); diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index d61f0a46847..bda27cd745e 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vnops.c,v 1.193 2023/04/26 10:00:37 beck Exp $ */ +/* $OpenBSD: nfs_vnops.c,v 1.194 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ /* @@ -1769,11 +1769,6 @@ nfs_link(void *v) info.nmi_v3 = NFS_ISV3(vp); - if (dvp->v_mount != vp->v_mount) { - pool_put(&namei_pool, cnp->cn_pnbuf); - vput(dvp); - return (EXDEV); - } error = vn_lock(vp, LK_EXCLUSIVE); if (error != 0) { VOP_ABORTOP(dvp, cnp); diff --git a/sys/tmpfs/tmpfs_vnops.c b/sys/tmpfs/tmpfs_vnops.c index d910b152362..b1c68fdebba 100644 --- a/sys/tmpfs/tmpfs_vnops.c +++ b/sys/tmpfs/tmpfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_vnops.c,v 1.53 2023/09/08 20:00:28 mvs Exp $ */ +/* $OpenBSD: tmpfs_vnops.c,v 1.54 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */ /* @@ -771,21 +771,8 @@ tmpfs_link(void *v) int error; KASSERT(VOP_ISLOCKED(dvp)); - - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - vput(dvp); - return EPERM; - } - KASSERT(dvp != vp); - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - vput(dvp); - return EXDEV; - } - dnode = VP_TO_TMPFS_DIR(dvp); node = VP_TO_TMPFS_NODE(vp); diff --git a/sys/ufs/ext2fs/ext2fs_vnops.c b/sys/ufs/ext2fs/ext2fs_vnops.c index 235590d7c74..eee8e11f8f1 100644 --- a/sys/ufs/ext2fs/ext2fs_vnops.c +++ b/sys/ufs/ext2fs/ext2fs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_vnops.c,v 1.91 2023/03/08 04:43:09 guenther Exp $ */ +/* $OpenBSD: ext2fs_vnops.c,v 1.92 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: ext2fs_vnops.c,v 1.1 1997/06/11 09:34:09 bouyer Exp $ */ /* @@ -435,16 +435,6 @@ ext2fs_link(void *v) if ((cnp->cn_flags & HASBUF) == 0) panic("ext2fs_link: no name"); #endif - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - error = EISDIR; - goto out2; - } - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - error = EXDEV; - goto out2; - } if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { VOP_ABORTOP(dvp, cnp); goto out2; diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index d6cee35a5b6..d3292849907 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.160 2024/02/03 18:51:59 beck Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.161 2024/03/25 17:57:07 guenther Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -621,16 +621,6 @@ ufs_link(void *v) if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_link: no name"); #endif - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - error = EPERM; - goto out2; - } - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - error = EXDEV; - goto out2; - } if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { VOP_ABORTOP(dvp, cnp); goto out2; -- 2.20.1