aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2023-07-22 11:03:33 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2023-07-22 11:03:33 +0000
commit6453d4240f6b46c718efa59651239f8519e1523e (patch)
tree46ebe55a69348a081184f400028891c0771a2ef6
parentd9c2dc6bf17b7710cbbac18bc0b913803b6c8a50 (diff)
downloadsrc-6453d4240f6b46c718efa59651239f8519e1523e.tar.gz
src-6453d4240f6b46c718efa59651239f8519e1523e.zip
vfs: Export exattr methods to reuse by Linuxulator
Reviewed by: Differential revision: https://reviews.freebsd.org/D35543 MFC after: 1 month
-rw-r--r--sys/kern/vfs_extattr.c245
-rw-r--r--sys/sys/extattr.h22
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;
@@ -686,19 +734,43 @@ struct extattr_list_fd_args {
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>