The branch main has been updated by dchagin:

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

commit 6453d4240f6b46c718efa59651239f8519e1523e
Author:     Dmitry Chagin <[email protected]>
AuthorDate: 2023-07-22 11:03:33 +0000
Commit:     Dmitry Chagin <[email protected]>
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>

Reply via email to