git: 6453d4240f6b - main - vfs: Export exattr methods to reuse by Linuxulator

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sat, 22 Jul 2023 11:09:17 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=6453d4240f6b46c718efa59651239f8519e1523e

commit 6453d4240f6b46c718efa59651239f8519e1523e
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-07-22 11:03:33 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-07-22 11:03:33 +0000

    vfs: Export exattr methods to reuse by Linuxulator
    
    Reviewed by:
    Differential revision:  https://reviews.freebsd.org/D35543
    MFC after:              1 month
---
 sys/kern/vfs_extattr.c | 245 ++++++++++++++++++++++++++++++++++---------------
 sys/sys/extattr.h      |  22 +++++
 2 files changed, 193 insertions(+), 74 deletions(-)

diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 4b2cd920f32b..d5f2101cf2d0 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -49,15 +49,15 @@ __FBSDID("$FreeBSD$");
 #include <security/audit/audit.h>
 #include <security/mac/mac_framework.h>
 
-static int	kern_extattr_set_path(struct thread *td, const char *path,
+static int	user_extattr_set_path(struct thread *td, const char *path,
 		    int attrnamespace, const char *attrname, void *data,
 		    size_t nbytes, int follow);
-static int	kern_extattr_get_path(struct thread *td, const char *path,
+static int	user_extattr_get_path(struct thread *td, const char *path,
 		    int attrnamespace, const char *attrname, void *data,
 		    size_t nbytes, int follow);
-static int	kern_extattr_delete_path(struct thread *td, const char *path,
+static int	user_extattr_delete_path(struct thread *td, const char *path,
 		    int attrnamespace, const char *attrname, int follow);
-static int	kern_extattr_list_path(struct thread *td, const char *path,
+static int	user_extattr_list_path(struct thread *td, const char *path,
 		    int attrnamespace, void *data, size_t nbytes, int follow);
 
 /*
@@ -232,25 +232,35 @@ struct extattr_set_fd_args {
 int
 sys_extattr_set_fd(struct thread *td, struct extattr_set_fd_args *uap)
 {
-	struct file *fp;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
-	cap_rights_t rights;
 	int error;
 
-	AUDIT_ARG_FD(uap->fd);
-	AUDIT_ARG_VALUE(uap->attrnamespace);
 	error = copyinstr(uap->attrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return (error);
+	return (kern_extattr_set_fd(td, uap->fd, uap->attrnamespace,
+	    attrname, uap->data, uap->nbytes));
+}
+
+int
+kern_extattr_set_fd(struct thread *td, int fd, int attrnamespace,
+    const char *attrname, void *data, size_t nbytes)
+{
+	struct file *fp;
+	cap_rights_t rights;
+	int error;
+
+	AUDIT_ARG_FD(fd);
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	error = getvnode_path(td, uap->fd,
+	error = getvnode_path(td, fd,
 	    cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp);
 	if (error)
 		return (error);
 
-	error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
-	    attrname, uap->data, uap->nbytes, td);
+	error = extattr_set_vp(fp->f_vnode, attrnamespace,
+	    attrname, data, nbytes, td);
 	fdrop(fp, td);
 
 	return (error);
@@ -269,7 +279,7 @@ int
 sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap)
 {
 
-	return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_set_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, uap->data, uap->nbytes, FOLLOW));
 }
 
@@ -286,25 +296,36 @@ int
 sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap)
 {
 
-	return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_set_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
 }
 
 static int
-kern_extattr_set_path(struct thread *td, const char *path, int attrnamespace,
+user_extattr_set_path(struct thread *td, const char *path, int attrnamespace,
     const char *uattrname, void *data, size_t nbytes, int follow)
 {
-	struct nameidata nd;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
 	int error;
 
-	AUDIT_ARG_VALUE(attrnamespace);
 	error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return (error);
+	return (kern_extattr_set_path(td, path, attrnamespace,
+	    attrname, data, nbytes, follow, UIO_USERSPACE));
+}
+
+int
+kern_extattr_set_path(struct thread *td, const char *path, int attrnamespace,
+    const char *attrname, void *data, size_t nbytes, int follow,
+    enum uio_seg pathseg)
+{
+	struct nameidata nd;
+	int error;
+
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
+	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path);
 	error = namei(&nd);
 	if (error)
 		return (error);
@@ -399,25 +420,35 @@ struct extattr_get_fd_args {
 int
 sys_extattr_get_fd(struct thread *td, struct extattr_get_fd_args *uap)
 {
-	struct file *fp;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
-	cap_rights_t rights;
 	int error;
 
-	AUDIT_ARG_FD(uap->fd);
-	AUDIT_ARG_VALUE(uap->attrnamespace);
 	error = copyinstr(uap->attrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return (error);
+	return (kern_extattr_get_fd(td, uap->fd, uap->attrnamespace,
+	    attrname, uap->data, uap->nbytes));
+}
+
+int
+kern_extattr_get_fd(struct thread *td, int fd, int attrnamespace,
+    const char *attrname, void *data, size_t nbytes)
+{
+	struct file *fp;
+	cap_rights_t rights;
+	int error;
+
+	AUDIT_ARG_FD(fd);
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	error = getvnode_path(td, uap->fd,
+	error = getvnode_path(td, fd,
 	    cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp);
 	if (error)
 		return (error);
 
-	error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
-	    attrname, uap->data, uap->nbytes, td);
+	error = extattr_get_vp(fp->f_vnode, attrnamespace,
+	    attrname, data, nbytes, td);
 
 	fdrop(fp, td);
 	return (error);
@@ -435,7 +466,7 @@ struct extattr_get_file_args {
 int
 sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap)
 {
-	return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_get_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, uap->data, uap->nbytes, FOLLOW));
 }
 
@@ -451,25 +482,36 @@ struct extattr_get_link_args {
 int
 sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap)
 {
-	return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_get_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
 }
 
 static int
-kern_extattr_get_path(struct thread *td, const char *path, int attrnamespace,
+user_extattr_get_path(struct thread *td, const char *path, int attrnamespace,
     const char *uattrname, void *data, size_t nbytes, int follow)
 {
-	struct nameidata nd;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
 	int error;
 
-	AUDIT_ARG_VALUE(attrnamespace);
 	error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return (error);
+	return (kern_extattr_get_path(td, path, attrnamespace,
+	    attrname, data, nbytes, follow, UIO_USERSPACE));
+}
+
+int
+kern_extattr_get_path(struct thread *td, const char *path, int attrnamespace,
+    const char *attrname, void *data, size_t nbytes, int follow,
+    enum uio_seg pathseg)
+{
+	struct nameidata nd;
+	int error;
+
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
+	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path);
 	error = namei(&nd);
 	if (error)
 		return (error);
@@ -534,24 +576,34 @@ struct extattr_delete_fd_args {
 int
 sys_extattr_delete_fd(struct thread *td, struct extattr_delete_fd_args *uap)
 {
-	struct file *fp;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
-	cap_rights_t rights;
 	int error;
 
-	AUDIT_ARG_FD(uap->fd);
-	AUDIT_ARG_VALUE(uap->attrnamespace);
 	error = copyinstr(uap->attrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return (error);
+	return (kern_extattr_delete_fd(td, uap->fd, uap->attrnamespace,
+	    attrname));
+}
+
+int
+kern_extattr_delete_fd(struct thread *td, int fd, int attrnamespace,
+    const char *attrname)
+{
+	struct file *fp;
+	cap_rights_t rights;
+	int error;
+
+	AUDIT_ARG_FD(fd);
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	error = getvnode_path(td, uap->fd,
+	error = getvnode_path(td, fd,
 	    cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), &fp);
 	if (error)
 		return (error);
 
-	error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
+	error = extattr_delete_vp(fp->f_vnode, attrnamespace,
 	    attrname, td);
 	fdrop(fp, td);
 	return (error);
@@ -568,7 +620,7 @@ int
 sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap)
 {
 
-	return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_delete_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, FOLLOW));
 }
 
@@ -583,25 +635,35 @@ int
 sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap)
 {
 
-	return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_delete_path(td, uap->path, uap->attrnamespace,
 	    uap->attrname, NOFOLLOW));
 }
 
-static int
-kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
+int
+user_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
     const char *uattrname, int follow)
 {
-	struct nameidata nd;
 	char attrname[EXTATTR_MAXNAMELEN + 1];
 	int error;
 
-	AUDIT_ARG_VALUE(attrnamespace);
 	error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
 	if (error)
 		return(error);
+	return (kern_extattr_delete_path(td, path, attrnamespace,
+	    attrname, follow, UIO_USERSPACE));
+}
+
+int
+kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
+    const char *attrname, int follow, enum uio_seg pathseg)
+{
+	struct nameidata nd;
+	int error;
+
+	AUDIT_ARG_VALUE(attrnamespace);
 	AUDIT_ARG_TEXT(attrname);
 
-	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
+	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path);
 	error = namei(&nd);
 	if (error)
 		return(error);
@@ -623,33 +685,19 @@ kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
  * References: vp must be a valid reference for the duration of the call
  */
 static int
-extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
-    size_t nbytes, struct thread *td)
+extattr_list_vp(struct vnode *vp, int attrnamespace, struct uio *auiop,
+    struct thread *td)
 {
-	struct uio auio, *auiop;
 	size_t size, *sizep;
-	struct iovec aiov;
 	ssize_t cnt;
 	int error;
 
-	if (nbytes > IOSIZE_MAX)
-		return (EINVAL);
-
-	auiop = NULL;
 	sizep = NULL;
 	cnt = 0;
-	if (data != NULL) {
-		aiov.iov_base = data;
-		aiov.iov_len = nbytes;
-		auio.uio_iov = &aiov;
-		auio.uio_iovcnt = 1;
-		auio.uio_offset = 0;
-		auio.uio_resid = nbytes;
-		auio.uio_rw = UIO_READ;
-		auio.uio_segflg = UIO_USERSPACE;
-		auio.uio_td = td;
-		auiop = &auio;
-		cnt = nbytes;
+	if (auiop != NULL) {
+		if (auiop->uio_resid > IOSIZE_MAX)
+			return (EINVAL);
+		cnt = auiop->uio_resid;
 	} else
 		sizep = &size;
 
@@ -668,7 +716,7 @@ extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
 	VOP_UNLOCK(vp);
 
 	if (auiop != NULL) {
-		cnt -= auio.uio_resid;
+		cnt -= auiop->uio_resid;
 		td->td_retval[0] = cnt;
 	} else
 		td->td_retval[0] = size;
@@ -685,20 +733,44 @@ struct extattr_list_fd_args {
 #endif
 int
 sys_extattr_list_fd(struct thread *td, struct extattr_list_fd_args *uap)
+{
+	struct uio auio, *auiop;
+	struct iovec aiov;
+
+	if (uap->data != NULL) {
+		aiov.iov_base = uap->data;
+		aiov.iov_len = uap->nbytes;
+		auio.uio_iov = &aiov;
+		auio.uio_iovcnt = 1;
+		auio.uio_offset = 0;
+		auio.uio_resid = uap->nbytes;
+		auio.uio_rw = UIO_READ;
+		auio.uio_segflg = UIO_USERSPACE;
+		auio.uio_td = td;
+		auiop = &auio;
+	} else
+		auiop = NULL;
+
+	return (kern_extattr_list_fd(td, uap->fd, uap->attrnamespace,
+	    auiop));
+}
+
+int
+kern_extattr_list_fd(struct thread *td, int fd, int attrnamespace,
+    struct uio *auiop)
 {
 	struct file *fp;
 	cap_rights_t rights;
 	int error;
 
-	AUDIT_ARG_FD(uap->fd);
-	AUDIT_ARG_VALUE(uap->attrnamespace);
-	error = getvnode_path(td, uap->fd,
+	AUDIT_ARG_FD(fd);
+	AUDIT_ARG_VALUE(attrnamespace);
+	error = getvnode_path(td, fd,
 	    cap_rights_init_one(&rights, CAP_EXTATTR_LIST), &fp);
 	if (error)
 		return (error);
 
-	error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
-	    uap->nbytes, td);
+	error = extattr_list_vp(fp->f_vnode, attrnamespace, auiop, td);
 
 	fdrop(fp, td);
 	return (error);
@@ -716,7 +788,7 @@ int
 sys_extattr_list_file(struct thread *td, struct extattr_list_file_args *uap)
 {
 
-	return (kern_extattr_list_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_list_path(td, uap->path, uap->attrnamespace,
 	    uap->data, uap->nbytes, FOLLOW));
 }
 
@@ -732,25 +804,50 @@ int
 sys_extattr_list_link(struct thread *td, struct extattr_list_link_args *uap)
 {
 
-	return (kern_extattr_list_path(td, uap->path, uap->attrnamespace,
+	return (user_extattr_list_path(td, uap->path, uap->attrnamespace,
 	    uap->data, uap->nbytes, NOFOLLOW));
 }
 
 static int
-kern_extattr_list_path(struct thread *td, const char *path, int attrnamespace,
+user_extattr_list_path(struct thread *td, const char *path, int attrnamespace,
     void *data, size_t nbytes, int follow)
+{
+	struct uio auio, *auiop;
+	struct iovec aiov;
+
+	if (data != NULL) {
+		aiov.iov_base = data;
+		aiov.iov_len = nbytes;
+		auio.uio_iov = &aiov;
+		auio.uio_iovcnt = 1;
+		auio.uio_offset = 0;
+		auio.uio_resid = nbytes;
+		auio.uio_rw = UIO_READ;
+		auio.uio_segflg = UIO_USERSPACE;
+		auio.uio_td = td;
+		auiop = &auio;
+	} else
+		auiop = NULL;
+
+	return (kern_extattr_list_path(td, path, attrnamespace,
+	    auiop, follow, UIO_USERSPACE));
+}
+
+int
+kern_extattr_list_path(struct thread *td, const char *path, int attrnamespace,
+    struct uio *auiop, int follow, enum uio_seg pathseg)
 {
 	struct nameidata nd;
 	int error;
 
 	AUDIT_ARG_VALUE(attrnamespace);
-	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
+	NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path);
 	error = namei(&nd);
 	if (error)
 		return (error);
 	NDFREE_PNBUF(&nd);
 
-	error = extattr_list_vp(nd.ni_vp, attrnamespace, data, nbytes, td);
+	error = extattr_list_vp(nd.ni_vp, attrnamespace, auiop, td);
 
 	vrele(nd.ni_vp);
 	return (error);
diff --git a/sys/sys/extattr.h b/sys/sys/extattr.h
index aa47f25985ce..f3ca2a8ea913 100644
--- a/sys/sys/extattr.h
+++ b/sys/sys/extattr.h
@@ -64,11 +64,33 @@
 #ifdef _KERNEL
 #include <sys/types.h>
 
+enum uio_seg;
+struct uio;
 struct thread;
 struct ucred;
 struct vnode;
 int	extattr_check_cred(struct vnode *vp, int attrnamespace,
 	    struct ucred *cred, struct thread *td, accmode_t accmode);
+int	kern_extattr_set_path(struct thread *td, const char *path,
+	    int attrnamespace, const char *attrname, void *data,
+	    size_t nbytes, int follow, enum uio_seg pathseg);
+int	kern_extattr_set_fd(struct thread *td, int fd, int attrnamespace,
+	    const char *attrname, void *data, size_t nbytes);
+int	kern_extattr_get_path(struct thread *td, const char *path,
+	    int attrnamespace, const char *attrname, void *data,
+	    size_t nbytes, int follow, enum uio_seg pathseg);
+int	kern_extattr_get_fd(struct thread *td, int fd, int attrnamespace,
+	    const char *attrname, void *data, size_t nbytes);
+int	kern_extattr_delete_path(struct thread *td, const char *path,
+	    int attrnamespace, const char *attrname, int follow,
+	    enum uio_seg pathseg);
+int	kern_extattr_delete_fd(struct thread *td, int fd, int attrnamespace,
+	    const char *attrname);
+int	kern_extattr_list_path(struct thread *td, const char *path,
+	    int attrnamespace, struct uio *auiop, int follow,
+	    enum uio_seg pathseg);
+int	kern_extattr_list_fd(struct thread *td, int fd, int attrnamespace,
+	    struct uio *auiop);
 
 #else
 #include <sys/cdefs.h>