git: 6453d4240f6b - main - vfs: Export exattr methods to reuse by Linuxulator
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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>