2018-06-06 05:42:14 +03:00
// SPDX-License-Identifier: GPL-2.0
2008-06-23 07:34:09 +04:00
/*
* Copyright ( C ) 2008 Christoph Hellwig .
* Portions Copyright ( C ) 2000 - 2008 Silicon Graphics , Inc .
*/
# include "xfs.h"
2019-06-29 05:25:35 +03:00
# include "xfs_shared.h"
2013-10-23 03:51:50 +04:00
# include "xfs_format.h"
2013-08-12 14:49:23 +04:00
# include "xfs_log_format.h"
2013-10-15 02:17:51 +04:00
# include "xfs_da_format.h"
2008-06-23 07:34:09 +04:00
# include "xfs_inode.h"
# include "xfs_attr.h"
2019-11-07 04:19:33 +03:00
# include "xfs_acl.h"
2020-02-27 04:30:33 +03:00
# include "xfs_da_format.h"
# include "xfs_da_btree.h"
2008-06-23 07:34:09 +04:00
# include <linux/posix_acl_xattr.h>
# include <linux/xattr.h>
static int
2016-04-11 03:48:24 +03:00
xfs_xattr_get ( const struct xattr_handler * handler , struct dentry * unused ,
struct inode * inode , const char * name , void * value , size_t size )
2008-06-23 07:34:09 +04:00
{
2020-02-27 04:30:34 +03:00
struct xfs_da_args args = {
. dp = XFS_I ( inode ) ,
. flags = handler - > flags ,
. name = name ,
. namelen = strlen ( name ) ,
. value = value ,
. valuelen = size ,
} ;
int error ;
2008-06-23 07:34:09 +04:00
2020-02-27 04:30:34 +03:00
error = xfs_attr_get ( & args ) ;
2008-06-23 07:34:09 +04:00
if ( error )
return error ;
2020-02-27 04:30:34 +03:00
return args . valuelen ;
2008-06-23 07:34:09 +04:00
}
2015-11-03 04:56:17 +03:00
void
xfs_forget_acl (
struct inode * inode ,
const char * name ,
int xflags )
{
/*
* Invalidate any cached ACLs if the user has bypassed the ACL
* interface . We don ' t validate the content whatsoever so it is caller
* responsibility to provide data in valid format and ensure i_mode is
* consistent .
*/
if ( xflags & ATTR_ROOT ) {
# ifdef CONFIG_XFS_POSIX_ACL
if ( ! strcmp ( name , SGI_ACL_FILE ) )
forget_cached_acl ( inode , ACL_TYPE_ACCESS ) ;
else if ( ! strcmp ( name , SGI_ACL_DEFAULT ) )
forget_cached_acl ( inode , ACL_TYPE_DEFAULT ) ;
# endif
}
}
2008-06-23 07:34:09 +04:00
static int
2016-05-27 17:19:30 +03:00
xfs_xattr_set ( const struct xattr_handler * handler , struct dentry * unused ,
struct inode * inode , const char * name , const void * value ,
size_t size , int flags )
2008-06-23 07:34:09 +04:00
{
2020-02-27 04:30:33 +03:00
struct xfs_da_args args = {
. dp = XFS_I ( inode ) ,
. flags = handler - > flags ,
. name = name ,
. namelen = strlen ( name ) ,
. value = ( void * ) value ,
. valuelen = size ,
} ;
2015-11-03 04:40:59 +03:00
int error ;
2008-06-23 07:34:09 +04:00
/* Convert Linux syscall to XFS internal ATTR flags */
if ( flags & XATTR_CREATE )
2020-02-27 04:30:33 +03:00
args . flags | = ATTR_CREATE ;
2008-06-23 07:34:09 +04:00
if ( flags & XATTR_REPLACE )
2020-02-27 04:30:33 +03:00
args . flags | = ATTR_REPLACE ;
2008-06-23 07:34:09 +04:00
2020-02-27 04:30:33 +03:00
error = xfs_attr_set ( & args ) ;
2015-11-03 04:56:17 +03:00
if ( ! error )
2020-02-27 04:30:33 +03:00
xfs_forget_acl ( inode , name , args . flags ) ;
2015-11-03 04:40:59 +03:00
return error ;
2008-06-23 07:34:09 +04:00
}
2010-05-14 04:53:20 +04:00
static const struct xattr_handler xfs_xattr_user_handler = {
2008-06-23 07:34:09 +04:00
. prefix = XATTR_USER_PREFIX ,
2009-11-13 12:52:56 +03:00
. flags = 0 , /* no flags implies user namespace */
. get = xfs_xattr_get ,
. set = xfs_xattr_set ,
2008-06-23 07:34:09 +04:00
} ;
2010-05-14 04:53:20 +04:00
static const struct xattr_handler xfs_xattr_trusted_handler = {
2008-06-23 07:34:09 +04:00
. prefix = XATTR_TRUSTED_PREFIX ,
2009-11-13 12:52:56 +03:00
. flags = ATTR_ROOT ,
. get = xfs_xattr_get ,
. set = xfs_xattr_set ,
2008-06-23 07:34:09 +04:00
} ;
2010-05-14 04:53:20 +04:00
static const struct xattr_handler xfs_xattr_security_handler = {
2008-06-23 07:34:09 +04:00
. prefix = XATTR_SECURITY_PREFIX ,
2009-11-13 12:52:56 +03:00
. flags = ATTR_SECURE ,
. get = xfs_xattr_get ,
. set = xfs_xattr_set ,
2008-06-23 07:34:09 +04:00
} ;
2010-05-14 04:53:20 +04:00
const struct xattr_handler * xfs_xattr_handlers [ ] = {
2008-06-23 07:34:09 +04:00
& xfs_xattr_user_handler ,
& xfs_xattr_trusted_handler ,
& xfs_xattr_security_handler ,
2009-06-10 19:07:47 +04:00
# ifdef CONFIG_XFS_POSIX_ACL
2013-12-20 17:16:50 +04:00
& posix_acl_access_xattr_handler ,
& posix_acl_default_xattr_handler ,
2009-06-10 19:07:47 +04:00
# endif
2008-06-23 07:34:09 +04:00
NULL
} ;
2016-12-05 04:32:14 +03:00
static void
2015-12-02 16:44:40 +03:00
__xfs_xattr_put_listent (
2010-01-20 02:47:48 +03:00
struct xfs_attr_list_context * context ,
2015-12-02 16:44:40 +03:00
char * prefix ,
int prefix_len ,
unsigned char * name ,
int namelen )
2008-06-23 07:34:09 +04:00
{
char * offset ;
int arraytop ;
2019-02-13 22:15:17 +03:00
if ( context - > count < 0 | | context - > seen_enough )
return ;
2020-02-27 04:30:37 +03:00
if ( ! context - > buffer )
2015-12-02 16:44:40 +03:00
goto compute_size ;
2008-06-23 07:34:09 +04:00
arraytop = context - > count + prefix_len + namelen + 1 ;
if ( arraytop > context - > firstu ) {
context - > count = - 1 ; /* insufficient space */
2016-09-14 00:40:35 +03:00
context - > seen_enough = 1 ;
2016-12-05 04:32:14 +03:00
return ;
2008-06-23 07:34:09 +04:00
}
2020-02-27 04:30:37 +03:00
offset = context - > buffer + context - > count ;
2015-12-02 16:44:40 +03:00
strncpy ( offset , prefix , prefix_len ) ;
2008-06-23 07:34:09 +04:00
offset + = prefix_len ;
2010-01-20 02:47:48 +03:00
strncpy ( offset , ( char * ) name , namelen ) ; /* real name */
2008-06-23 07:34:09 +04:00
offset + = namelen ;
* offset = ' \0 ' ;
2015-12-02 16:44:40 +03:00
compute_size :
2008-06-23 07:34:09 +04:00
context - > count + = prefix_len + namelen + 1 ;
2016-12-05 04:32:14 +03:00
return ;
2008-06-23 07:34:09 +04:00
}
2016-12-05 04:32:14 +03:00
static void
2015-12-02 16:44:40 +03:00
xfs_xattr_put_listent (
2010-01-20 02:47:48 +03:00
struct xfs_attr_list_context * context ,
int flags ,
unsigned char * name ,
int namelen ,
2016-04-06 00:57:32 +03:00
int valuelen )
2008-06-23 07:34:09 +04:00
{
2015-12-02 16:44:40 +03:00
char * prefix ;
int prefix_len ;
2008-06-23 07:34:09 +04:00
2015-12-02 16:44:40 +03:00
ASSERT ( context - > count > = 0 ) ;
2008-06-23 07:34:09 +04:00
2015-12-02 16:44:40 +03:00
if ( flags & XFS_ATTR_ROOT ) {
# ifdef CONFIG_XFS_POSIX_ACL
if ( namelen = = SGI_ACL_FILE_SIZE & &
strncmp ( name , SGI_ACL_FILE ,
SGI_ACL_FILE_SIZE ) = = 0 ) {
2016-12-05 04:32:14 +03:00
__xfs_xattr_put_listent (
2015-12-02 16:44:40 +03:00
context , XATTR_SYSTEM_PREFIX ,
XATTR_SYSTEM_PREFIX_LEN ,
XATTR_POSIX_ACL_ACCESS ,
strlen ( XATTR_POSIX_ACL_ACCESS ) ) ;
} else if ( namelen = = SGI_ACL_DEFAULT_SIZE & &
strncmp ( name , SGI_ACL_DEFAULT ,
SGI_ACL_DEFAULT_SIZE ) = = 0 ) {
2016-12-05 04:32:14 +03:00
__xfs_xattr_put_listent (
2015-12-02 16:44:40 +03:00
context , XATTR_SYSTEM_PREFIX ,
XATTR_SYSTEM_PREFIX_LEN ,
XATTR_POSIX_ACL_DEFAULT ,
strlen ( XATTR_POSIX_ACL_DEFAULT ) ) ;
}
# endif
2008-06-23 07:34:09 +04:00
2015-12-02 16:44:40 +03:00
/*
* Only show root namespace entries if we are actually allowed to
* see them .
*/
if ( ! capable ( CAP_SYS_ADMIN ) )
2016-12-05 04:32:14 +03:00
return ;
2015-12-02 16:44:40 +03:00
prefix = XATTR_TRUSTED_PREFIX ;
prefix_len = XATTR_TRUSTED_PREFIX_LEN ;
} else if ( flags & XFS_ATTR_SECURE ) {
prefix = XATTR_SECURITY_PREFIX ;
prefix_len = XATTR_SECURITY_PREFIX_LEN ;
} else {
prefix = XATTR_USER_PREFIX ;
prefix_len = XATTR_USER_PREFIX_LEN ;
}
2016-12-05 04:32:14 +03:00
__xfs_xattr_put_listent ( context , prefix , prefix_len , name ,
namelen ) ;
return ;
2008-06-23 07:34:09 +04:00
}
ssize_t
2016-04-06 00:57:18 +03:00
xfs_vn_listxattr (
struct dentry * dentry ,
char * data ,
size_t size )
2008-06-23 07:34:09 +04:00
{
struct xfs_attr_list_context context ;
struct attrlist_cursor_kern cursor = { 0 } ;
2016-04-06 00:57:18 +03:00
struct inode * inode = d_inode ( dentry ) ;
int error ;
2008-06-23 07:34:09 +04:00
/*
* First read the regular on - disk attributes .
*/
memset ( & context , 0 , sizeof ( context ) ) ;
context . dp = XFS_I ( inode ) ;
context . cursor = & cursor ;
context . resynch = 1 ;
2020-02-27 04:30:37 +03:00
context . buffer = size ? data : NULL ;
2008-06-23 07:34:09 +04:00
context . bufsize = size ;
context . firstu = context . bufsize ;
2015-12-02 16:44:40 +03:00
context . put_listent = xfs_xattr_put_listent ;
2008-06-23 07:34:09 +04:00
2016-04-06 00:57:18 +03:00
error = xfs_attr_list_int ( & context ) ;
if ( error )
return error ;
2008-06-23 07:34:09 +04:00
if ( context . count < 0 )
return - ERANGE ;
return context . count ;
}