Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/vfs_extattr.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/extattr.h> | #include <sys/extattr.h> | ||||
#include <security/audit/audit.h> | #include <security/audit/audit.h> | ||||
#include <security/mac/mac_framework.h> | #include <security/mac/mac_framework.h> | ||||
static int kern_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, | |||||
int attrnamespace, const char *attrname, void *data, | |||||
size_t nbytes, int follow); | |||||
static int kern_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, | |||||
int attrnamespace, void *data, size_t nbytes, int follow); | |||||
/* | /* | ||||
* Syscall to push extended attribute configuration information into the VFS. | * Syscall to push extended attribute configuration information into the VFS. | ||||
* Accepts a path, which it converts to a mountpoint, as well as a command | * Accepts a path, which it converts to a mountpoint, as well as a command | ||||
* (int cmd), and attribute name and misc data. | * (int cmd), and attribute name and misc data. | ||||
* | * | ||||
* Currently this is used only by UFS1 extended attributes. | * Currently this is used only by UFS1 extended attributes. | ||||
*/ | */ | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | struct extattr_set_file_args { | ||||
const char *attrname; | const char *attrname; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap) | sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap) | ||||
{ | { | ||||
struct nameidata nd; | |||||
char attrname[EXTATTR_MAXNAMELEN]; | |||||
int error; | |||||
AUDIT_ARG_VALUE(uap->attrnamespace); | return (kern_extattr_set_path(td, uap->path, uap->attrnamespace, | ||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | uap->attrname, uap->data, uap->nbytes, FOLLOW)); | ||||
if (error) | |||||
return (error); | |||||
AUDIT_ARG_TEXT(attrname); | |||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, | |||||
uap->path, td); | |||||
error = namei(&nd); | |||||
if (error) | |||||
return (error); | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, | |||||
uap->data, uap->nbytes, td); | |||||
vrele(nd.ni_vp); | |||||
return (error); | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct extattr_set_link_args { | struct extattr_set_link_args { | ||||
const char *path; | const char *path; | ||||
int attrnamespace; | int attrnamespace; | ||||
const char *attrname; | const char *attrname; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap) | sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap) | ||||
{ | { | ||||
return (kern_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, | |||||
const char *uattrname, void *data, size_t nbytes, int follow) | |||||
{ | |||||
struct nameidata nd; | struct nameidata nd; | ||||
char attrname[EXTATTR_MAXNAMELEN]; | char attrname[EXTATTR_MAXNAMELEN]; | ||||
int error; | int error; | ||||
AUDIT_ARG_VALUE(uap->attrnamespace); | AUDIT_ARG_VALUE(attrnamespace); | ||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
AUDIT_ARG_TEXT(attrname); | AUDIT_ARG_TEXT(attrname); | ||||
NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, | NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td); | ||||
uap->path, td); | |||||
error = namei(&nd); | error = namei(&nd); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, | error = extattr_set_vp(nd.ni_vp, attrnamespace, attrname, data, | ||||
uap->data, uap->nbytes, td); | nbytes, td); | ||||
vrele(nd.ni_vp); | vrele(nd.ni_vp); | ||||
return (error); | return (error); | ||||
} | } | ||||
/*- | /*- | ||||
* Get a named extended attribute on a file or directory | * Get a named extended attribute on a file or directory | ||||
* | * | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | struct extattr_get_file_args { | ||||
const char *attrname; | const char *attrname; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap) | sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap) | ||||
{ | { | ||||
struct nameidata nd; | return (kern_extattr_get_path(td, uap->path, uap->attrnamespace, | ||||
char attrname[EXTATTR_MAXNAMELEN]; | uap->attrname, uap->data, uap->nbytes, FOLLOW)); | ||||
int error; | |||||
AUDIT_ARG_VALUE(uap->attrnamespace); | |||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | |||||
if (error) | |||||
return (error); | |||||
AUDIT_ARG_TEXT(attrname); | |||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td); | |||||
error = namei(&nd); | |||||
if (error) | |||||
return (error); | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, | |||||
uap->data, uap->nbytes, td); | |||||
vrele(nd.ni_vp); | |||||
return (error); | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct extattr_get_link_args { | struct extattr_get_link_args { | ||||
const char *path; | const char *path; | ||||
int attrnamespace; | int attrnamespace; | ||||
const char *attrname; | const char *attrname; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap) | sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap) | ||||
{ | { | ||||
return (kern_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, | |||||
const char *uattrname, void *data, size_t nbytes, int follow) | |||||
{ | |||||
struct nameidata nd; | struct nameidata nd; | ||||
char attrname[EXTATTR_MAXNAMELEN]; | char attrname[EXTATTR_MAXNAMELEN]; | ||||
int error; | int error; | ||||
AUDIT_ARG_VALUE(uap->attrnamespace); | AUDIT_ARG_VALUE(attrnamespace); | ||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
AUDIT_ARG_TEXT(attrname); | AUDIT_ARG_TEXT(attrname); | ||||
NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, | NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td); | ||||
td); | |||||
error = namei(&nd); | error = namei(&nd); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, | error = extattr_get_vp(nd.ni_vp, attrnamespace, attrname, data, | ||||
uap->data, uap->nbytes, td); | nbytes, td); | ||||
vrele(nd.ni_vp); | vrele(nd.ni_vp); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* extattr_delete_vp(): Delete a named extended attribute on a file or | * extattr_delete_vp(): Delete a named extended attribute on a file or | ||||
* directory | * directory | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | struct extattr_delete_file_args { | ||||
const char *path; | const char *path; | ||||
int attrnamespace; | int attrnamespace; | ||||
const char *attrname; | const char *attrname; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap) | sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap) | ||||
{ | { | ||||
struct nameidata nd; | |||||
char attrname[EXTATTR_MAXNAMELEN]; | |||||
int error; | |||||
AUDIT_ARG_VALUE(uap->attrnamespace); | return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace, | ||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | uap->attrname, FOLLOW)); | ||||
if (error) | |||||
return(error); | |||||
AUDIT_ARG_TEXT(attrname); | |||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td); | |||||
error = namei(&nd); | |||||
if (error) | |||||
return(error); | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td); | |||||
vrele(nd.ni_vp); | |||||
return(error); | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct extattr_delete_link_args { | struct extattr_delete_link_args { | ||||
const char *path; | const char *path; | ||||
int attrnamespace; | int attrnamespace; | ||||
const char *attrname; | const char *attrname; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap) | sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap) | ||||
{ | { | ||||
return (kern_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, | |||||
const char *uattrname, int follow) | |||||
{ | |||||
struct nameidata nd; | struct nameidata nd; | ||||
char attrname[EXTATTR_MAXNAMELEN]; | char attrname[EXTATTR_MAXNAMELEN]; | ||||
int error; | int error; | ||||
AUDIT_ARG_VALUE(uap->attrnamespace); | AUDIT_ARG_VALUE(attrnamespace); | ||||
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); | error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL); | ||||
if (error) | if (error) | ||||
return(error); | return(error); | ||||
AUDIT_ARG_TEXT(attrname); | AUDIT_ARG_TEXT(attrname); | ||||
NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td); | NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td); | ||||
error = namei(&nd); | error = namei(&nd); | ||||
if (error) | if (error) | ||||
return(error); | return(error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td); | error = extattr_delete_vp(nd.ni_vp, attrnamespace, attrname, td); | ||||
vrele(nd.ni_vp); | vrele(nd.ni_vp); | ||||
return(error); | return(error); | ||||
} | } | ||||
/*- | /*- | ||||
* Retrieve a list of extended attributes on a file or directory. | * Retrieve a list of extended attributes on a file or directory. | ||||
* | * | ||||
* Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace", | * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace", | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | struct extattr_list_file_args { | ||||
int attrnamespace; | int attrnamespace; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
} | } | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_list_file(struct thread *td, struct extattr_list_file_args *uap) | sys_extattr_list_file(struct thread *td, struct extattr_list_file_args *uap) | ||||
{ | { | ||||
struct nameidata nd; | |||||
int error; | |||||
AUDIT_ARG_VALUE(uap->attrnamespace); | return (kern_extattr_list_path(td, uap->path, uap->attrnamespace, | ||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td); | uap->data, uap->nbytes, FOLLOW)); | ||||
error = namei(&nd); | |||||
if (error) | |||||
return (error); | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, | |||||
uap->nbytes, td); | |||||
vrele(nd.ni_vp); | |||||
return (error); | |||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct extattr_list_link_args { | struct extattr_list_link_args { | ||||
const char *path; | const char *path; | ||||
int attrnamespace; | int attrnamespace; | ||||
void *data; | void *data; | ||||
size_t nbytes; | size_t nbytes; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_extattr_list_link(struct thread *td, struct extattr_list_link_args *uap) | sys_extattr_list_link(struct thread *td, struct extattr_list_link_args *uap) | ||||
{ | { | ||||
return (kern_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, | |||||
void *data, size_t nbytes, int follow) | |||||
{ | |||||
struct nameidata nd; | struct nameidata nd; | ||||
int error; | int error; | ||||
AUDIT_ARG_VALUE(uap->attrnamespace); | AUDIT_ARG_VALUE(attrnamespace); | ||||
NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, | NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td); | ||||
td); | |||||
error = namei(&nd); | error = namei(&nd); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, | error = extattr_list_vp(nd.ni_vp, attrnamespace, data, nbytes, td); | ||||
uap->nbytes, td); | |||||
vrele(nd.ni_vp); | vrele(nd.ni_vp); | ||||
return (error); | return (error); | ||||
} | } |