mirror of
https://github.com/opnsense/src.git
synced 2026-06-15 19:49:16 -04:00
vfs: Export exattr methods to reuse by Linuxulator
Reviewed by: Differential revision: https://reviews.freebsd.org/D35543 MFC after: 1 month
This commit is contained in:
parent
d9c2dc6bf1
commit
6453d4240f
2 changed files with 193 additions and 74 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue