Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
663be8db
Commit
663be8db
authored
Jan 10, 2004
by
Nathan Scott
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[XFS] Rework some extended attributes code to make it more easily extended.
SGI Modid: 2.5.x-xfs:slinx:163383a
parent
6bda7ecb
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
426 additions
and
263 deletions
+426
-263
fs/xfs/linux/xfs_iops.c
fs/xfs/linux/xfs_iops.c
+42
-205
fs/xfs/linux/xfs_iops.h
fs/xfs/linux/xfs_iops.h
+1
-25
fs/xfs/xfs_acl.h
fs/xfs/xfs_acl.h
+3
-1
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.c
+306
-1
fs/xfs/xfs_attr.h
fs/xfs/xfs_attr.h
+39
-5
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_leaf.c
+30
-23
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_attr_leaf.h
+5
-3
No files found.
fs/xfs/linux/xfs_iops.c
View file @
663be8db
...
...
@@ -110,7 +110,7 @@ linvfs_mknod(
vattr_t
va
;
vnode_t
*
vp
=
NULL
,
*
dvp
=
LINVFS_GET_VP
(
dir
);
xfs_acl_t
*
default_acl
=
NULL
;
xattr_
exists_t
test_default_acl
=
_ACL_DEFAULT_EXISTS
;
attr
exists_t
test_default_acl
=
_ACL_DEFAULT_EXISTS
;
int
error
;
/*
...
...
@@ -552,61 +552,6 @@ linvfs_truncate(
block_truncate_page
(
inode
->
i_mapping
,
inode
->
i_size
,
linvfs_get_block
);
}
/*
* Extended attributes interfaces
*/
#define SYSTEM_NAME "system."
/* VFS shared names/values */
#define ROOT_NAME "trusted."
/* root's own names/values */
#define USER_NAME "user."
/* user's own names/values */
STATIC
xattr_namespace_t
xfs_namespace_array
[]
=
{
{
.
name
=
SYSTEM_NAME
,
.
namelen
=
sizeof
(
SYSTEM_NAME
)
-
1
,.
exists
=
NULL
},
{
.
name
=
ROOT_NAME
,
.
namelen
=
sizeof
(
ROOT_NAME
)
-
1
,
.
exists
=
NULL
},
{
.
name
=
USER_NAME
,
.
namelen
=
sizeof
(
USER_NAME
)
-
1
,
.
exists
=
NULL
},
{
.
name
=
NULL
}
};
xattr_namespace_t
*
xfs_namespaces
=
&
xfs_namespace_array
[
0
];
#define POSIXACL_ACCESS "posix_acl_access"
#define POSIXACL_ACCESS_SIZE (sizeof(POSIXACL_ACCESS)-1)
#define POSIXACL_DEFAULT "posix_acl_default"
#define POSIXACL_DEFAULT_SIZE (sizeof(POSIXACL_DEFAULT)-1)
#define POSIXCAP "posix_capabilities"
#define POSIXCAP_SIZE (sizeof(POSIXCAP)-1)
#define POSIXMAC "posix_mac"
#define POSIXMAC_SIZE (sizeof(POSIXMAC)-1)
STATIC
xattr_namespace_t
sys_namespace_array
[]
=
{
{
.
name
=
POSIXACL_ACCESS
,
.
namelen
=
POSIXACL_ACCESS_SIZE
,
.
exists
=
_ACL_ACCESS_EXISTS
},
{
.
name
=
POSIXACL_DEFAULT
,
.
namelen
=
POSIXACL_DEFAULT_SIZE
,
.
exists
=
_ACL_DEFAULT_EXISTS
},
{
.
name
=
POSIXCAP
,
.
namelen
=
POSIXCAP_SIZE
,
.
exists
=
_CAP_EXISTS
},
{
.
name
=
POSIXMAC
,
.
namelen
=
POSIXMAC_SIZE
,
.
exists
=
_MAC_EXISTS
},
{
.
name
=
NULL
}
};
/*
* Some checks to prevent people abusing EAs to get over quota:
* - Don't allow modifying user EAs on devices/symlinks;
* - Don't allow modifying user EAs if sticky bit set;
*/
STATIC
int
capable_user_xattr
(
struct
inode
*
inode
)
{
if
(
!
S_ISREG
(
inode
->
i_mode
)
&&
!
S_ISDIR
(
inode
->
i_mode
)
&&
!
capable
(
CAP_SYS_ADMIN
))
return
0
;
if
(
S_ISDIR
(
inode
->
i_mode
)
&&
(
inode
->
i_mode
&
S_ISVTX
)
&&
(
current
->
fsuid
!=
inode
->
i_uid
)
&&
!
capable
(
CAP_FOWNER
))
return
0
;
return
1
;
}
STATIC
int
linvfs_setxattr
(
struct
dentry
*
dentry
,
...
...
@@ -615,59 +560,27 @@ linvfs_setxattr(
size_t
size
,
int
flags
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
)
;
char
*
p
=
(
char
*
)
name
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
dentry
->
d_inode
)
;
char
*
attr
=
(
char
*
)
name
;
attrnames_t
*
namesp
;
int
xflags
=
0
;
int
error
;
if
(
strncmp
(
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
)
==
0
)
{
error
=
-
EINVAL
;
if
(
flags
&
XATTR_CREATE
)
return
error
;
error
=
-
EOPNOTSUPP
;
p
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
if
(
strcmp
(
p
,
POSIXACL_ACCESS
)
==
0
)
error
=
xfs_acl_vset
(
vp
,
(
void
*
)
data
,
size
,
_ACL_TYPE_ACCESS
);
else
if
(
strcmp
(
p
,
POSIXACL_DEFAULT
)
==
0
)
error
=
xfs_acl_vset
(
vp
,
(
void
*
)
data
,
size
,
_ACL_TYPE_DEFAULT
);
else
if
(
strcmp
(
p
,
POSIXCAP
)
==
0
)
error
=
xfs_cap_vset
(
vp
,
(
void
*
)
data
,
size
);
if
(
!
error
)
error
=
vn_revalidate
(
vp
);
namesp
=
attr_lookup_namespace
(
attr
,
attr_namespaces
,
ATTR_NAMECOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
attr
+=
namesp
->
attr_namelen
;
error
=
namesp
->
attr_capable
(
vp
,
NULL
);
if
(
error
)
return
error
;
}
if
(
IS_IMMUTABLE
(
inode
)
||
IS_APPEND
(
inode
))
return
-
EPERM
;
/* Convert Linux syscall to XFS internal ATTR flags */
if
(
flags
&
XATTR_CREATE
)
xflags
|=
ATTR_CREATE
;
if
(
flags
&
XATTR_REPLACE
)
xflags
|=
ATTR_REPLACE
;
if
(
strncmp
(
name
,
xfs_namespaces
[
ROOT_NAMES
].
name
,
xfs_namespaces
[
ROOT_NAMES
].
namelen
)
==
0
)
{
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
xflags
|=
ATTR_ROOT
;
p
+=
xfs_namespaces
[
ROOT_NAMES
].
namelen
;
VOP_ATTR_SET
(
vp
,
p
,
(
void
*
)
data
,
size
,
xflags
,
NULL
,
error
);
return
-
error
;
}
if
(
strncmp
(
name
,
xfs_namespaces
[
USER_NAMES
].
name
,
xfs_namespaces
[
USER_NAMES
].
namelen
)
==
0
)
{
if
(
!
capable_user_xattr
(
inode
))
return
-
EPERM
;
p
+=
xfs_namespaces
[
USER_NAMES
].
namelen
;
VOP_ATTR_SET
(
vp
,
p
,
(
void
*
)
data
,
size
,
xflags
,
NULL
,
error
);
return
-
error
;
}
return
-
EOPNOTSUPP
;
xflags
|=
namesp
->
attr_flag
;
return
namesp
->
attr_set
(
vp
,
attr
,
(
void
*
)
data
,
size
,
xflags
);
}
STATIC
ssize_t
...
...
@@ -677,53 +590,27 @@ linvfs_getxattr(
void
*
data
,
size_t
size
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
)
;
char
*
p
=
(
char
*
)
name
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
dentry
->
d_inode
)
;
char
*
attr
=
(
char
*
)
name
;
attrnames_t
*
namesp
;
int
xflags
=
0
;
ssize_t
error
;
if
(
strncmp
(
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
)
==
0
)
{
error
=
-
EOPNOTSUPP
;
p
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
if
(
strcmp
(
p
,
POSIXACL_ACCESS
)
==
0
)
error
=
xfs_acl_vget
(
vp
,
data
,
size
,
_ACL_TYPE_ACCESS
);
else
if
(
strcmp
(
p
,
POSIXACL_DEFAULT
)
==
0
)
error
=
xfs_acl_vget
(
vp
,
data
,
size
,
_ACL_TYPE_DEFAULT
);
else
if
(
strcmp
(
p
,
POSIXCAP
)
==
0
)
error
=
xfs_cap_vget
(
vp
,
data
,
size
);
namesp
=
attr_lookup_namespace
(
attr
,
attr_namespaces
,
ATTR_NAMECOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
attr
+=
namesp
->
attr_namelen
;
error
=
namesp
->
attr_capable
(
vp
,
NULL
);
if
(
error
)
return
error
;
}
/* Convert Linux syscall to XFS internal ATTR flags */
if
(
!
size
)
{
xflags
|=
ATTR_KERNOVAL
;
data
=
NULL
;
}
if
(
strncmp
(
name
,
xfs_namespaces
[
ROOT_NAMES
].
name
,
xfs_namespaces
[
ROOT_NAMES
].
namelen
)
==
0
)
{
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
xflags
|=
ATTR_ROOT
;
p
+=
xfs_namespaces
[
ROOT_NAMES
].
namelen
;
VOP_ATTR_GET
(
vp
,
p
,
data
,
(
int
*
)
&
size
,
xflags
,
NULL
,
error
);
if
(
!
error
)
error
=
-
size
;
return
-
error
;
}
if
(
strncmp
(
name
,
xfs_namespaces
[
USER_NAMES
].
name
,
xfs_namespaces
[
USER_NAMES
].
namelen
)
==
0
)
{
p
+=
xfs_namespaces
[
USER_NAMES
].
namelen
;
if
(
!
capable_user_xattr
(
inode
))
return
-
EPERM
;
VOP_ATTR_GET
(
vp
,
p
,
data
,
(
int
*
)
&
size
,
xflags
,
NULL
,
error
);
if
(
!
error
)
error
=
-
size
;
return
-
error
;
}
return
-
EOPNOTSUPP
;
xflags
|=
namesp
->
attr_flag
;
return
namesp
->
attr_get
(
vp
,
attr
,
(
void
*
)
data
,
size
,
xflags
);
}
STATIC
ssize_t
...
...
@@ -732,40 +619,18 @@ linvfs_listxattr(
char
*
data
,
size_t
size
)
{
attrlist_cursor_kern_t
cursor
;
xattr_namespace_t
*
sys
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
dentry
->
d_inode
);
char
*
k
=
data
;
int
xflags
=
ATTR_KERNAMELS
;
int
result
=
0
;
ssize_t
error
;
int
error
,
xflags
=
ATTR_KERNAMELS
;
ssize_t
result
;
if
(
!
size
)
xflags
|=
ATTR_KERNOVAL
;
if
(
capable
(
CAP_SYS_ADMIN
))
xflags
|=
ATTR_KERNFULLS
;
memset
(
&
cursor
,
0
,
sizeof
(
cursor
));
VOP_ATTR_LIST
(
vp
,
data
,
size
,
xflags
,
&
cursor
,
NULL
,
error
);
if
(
error
>
0
)
return
-
error
;
result
+=
-
error
;
k
+=
result
;
/* advance start of our buffer */
for
(
sys
=
&
sys_namespace_array
[
0
];
sys
->
name
!=
NULL
;
sys
++
)
{
if
(
sys
->
exists
==
NULL
||
!
sys
->
exists
(
vp
))
continue
;
result
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
result
+=
sys
->
namelen
+
1
;
if
(
size
)
{
if
(
result
>
size
)
return
-
ERANGE
;
strcpy
(
k
,
xfs_namespaces
[
SYSTEM_NAMES
].
name
);
k
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
strcpy
(
k
,
sys
->
name
);
k
+=
sys
->
namelen
+
1
;
}
}
error
=
attr_generic_list
(
vp
,
data
,
size
,
xflags
,
&
result
);
if
(
error
<
0
)
return
error
;
return
result
;
}
...
...
@@ -774,51 +639,25 @@ linvfs_removexattr(
struct
dentry
*
dentry
,
const
char
*
name
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
)
;
char
*
p
=
(
char
*
)
name
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
dentry
->
d_inode
)
;
char
*
attr
=
(
char
*
)
name
;
attrnames_t
*
namesp
;
int
xflags
=
0
;
int
error
;
if
(
strncmp
(
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
name
,
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
)
==
0
)
{
error
=
-
EOPNOTSUPP
;
p
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
if
(
strcmp
(
p
,
POSIXACL_ACCESS
)
==
0
)
error
=
xfs_acl_vremove
(
vp
,
_ACL_TYPE_ACCESS
);
else
if
(
strcmp
(
p
,
POSIXACL_DEFAULT
)
==
0
)
error
=
xfs_acl_vremove
(
vp
,
_ACL_TYPE_DEFAULT
);
else
if
(
strcmp
(
p
,
POSIXCAP
)
==
0
)
error
=
xfs_cap_vremove
(
vp
);
namesp
=
attr_lookup_namespace
(
attr
,
attr_namespaces
,
ATTR_NAMECOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
attr
+=
namesp
->
attr_namelen
;
error
=
namesp
->
attr_capable
(
vp
,
NULL
);
if
(
error
)
return
error
;
}
if
(
IS_IMMUTABLE
(
inode
)
||
IS_APPEND
(
inode
))
return
-
EPERM
;
if
(
strncmp
(
name
,
xfs_namespaces
[
ROOT_NAMES
].
name
,
xfs_namespaces
[
ROOT_NAMES
].
namelen
)
==
0
)
{
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
xflags
|=
ATTR_ROOT
;
p
+=
xfs_namespaces
[
ROOT_NAMES
].
namelen
;
VOP_ATTR_REMOVE
(
vp
,
p
,
xflags
,
NULL
,
error
);
return
-
error
;
}
if
(
strncmp
(
name
,
xfs_namespaces
[
USER_NAMES
].
name
,
xfs_namespaces
[
USER_NAMES
].
namelen
)
==
0
)
{
p
+=
xfs_namespaces
[
USER_NAMES
].
namelen
;
if
(
!
capable_user_xattr
(
inode
))
return
-
EPERM
;
VOP_ATTR_REMOVE
(
vp
,
p
,
xflags
,
NULL
,
error
);
return
-
error
;
}
return
-
EOPNOTSUPP
;
xflags
|=
namesp
->
attr_flag
;
return
namesp
->
attr_remove
(
vp
,
attr
,
xflags
);
}
struct
inode_operations
linvfs_file_inode_operations
=
{
struct
inode_operations
linvfs_file_inode_operations
=
{
.
permission
=
linvfs_permission
,
.
truncate
=
linvfs_truncate
,
.
getattr
=
linvfs_getattr
,
...
...
@@ -829,8 +668,7 @@ struct inode_operations linvfs_file_inode_operations =
.
removexattr
=
linvfs_removexattr
,
};
struct
inode_operations
linvfs_dir_inode_operations
=
{
struct
inode_operations
linvfs_dir_inode_operations
=
{
.
create
=
linvfs_create
,
.
lookup
=
linvfs_lookup
,
.
link
=
linvfs_link
,
...
...
@@ -849,8 +687,7 @@ struct inode_operations linvfs_dir_inode_operations =
.
removexattr
=
linvfs_removexattr
,
};
struct
inode_operations
linvfs_symlink_inode_operations
=
{
struct
inode_operations
linvfs_symlink_inode_operations
=
{
.
readlink
=
linvfs_readlink
,
.
follow_link
=
linvfs_follow_link
,
.
permission
=
linvfs_permission
,
...
...
fs/xfs/linux/xfs_iops.h
View file @
663be8db
/*
* Copyright (c) 2000-200
2
Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-200
3
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -32,30 +32,6 @@
#ifndef __XFS_IOPS_H__
#define __XFS_IOPS_H__
/*
* Extended system attributes.
* So far only POSIX ACLs are supported, but this will need to
* grow in time (capabilities, mandatory access control, etc).
*/
#define XFS_SYSTEM_NAMESPACE SYSTEM_POSIXACL
/*
* Define a table of the namespaces XFS supports
*/
typedef
int
(
*
xattr_exists_t
)(
vnode_t
*
);
typedef
struct
xattr_namespace
{
char
*
name
;
unsigned
int
namelen
;
xattr_exists_t
exists
;
}
xattr_namespace_t
;
#define SYSTEM_NAMES 0
#define ROOT_NAMES 1
#define USER_NAMES 2
extern
struct
xattr_namespace
*
xfs_namespaces
;
extern
struct
inode_operations
linvfs_file_inode_operations
;
extern
struct
inode_operations
linvfs_dir_inode_operations
;
extern
struct
inode_operations
linvfs_symlink_inode_operations
;
...
...
fs/xfs/xfs_acl.h
View file @
663be8db
/*
* Copyright (c) 2001-200
2
Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2001-200
3
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -102,6 +102,8 @@ extern struct kmem_zone *xfs_acl_zone;
#define xfs_acl_vset(v,p,sz,t) (-EOPNOTSUPP)
#define xfs_acl_vget(v,p,sz,t) (-EOPNOTSUPP)
#define xfs_acl_vremove(v,t) (-EOPNOTSUPP)
#define xfs_acl_vhasacl_access(v) (0)
#define xfs_acl_vhasacl_default(v) (0)
#define _ACL_DECL(a) ((void)0)
#define _ACL_ALLOC(a) (1)
/* successfully allocate nothing */
#define _ACL_FREE(a) ((void)0)
...
...
fs/xfs/xfs_attr.c
View file @
663be8db
/*
* Copyright (c) 2000-200
2
Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-200
3
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -63,6 +63,7 @@
#include "xfs_quota.h"
#include "xfs_rw.h"
#include "xfs_trans_space.h"
#include "xfs_acl.h"
/*
* xfs_attr.c
...
...
@@ -2357,3 +2358,307 @@ xfs_attr_trace_enter(int type, char *where,
(
void
*
)
a14
,
(
void
*
)
a15
);
}
#endif
/* XFS_ATTR_TRACE */
/*========================================================================
* System (pseudo) namespace attribute interface routines.
*========================================================================*/
STATIC
int
posix_acl_access_set
(
vnode_t
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
return
xfs_acl_vset
(
vp
,
data
,
size
,
_ACL_TYPE_ACCESS
);
}
STATIC
int
posix_acl_access_remove
(
struct
vnode
*
vp
,
char
*
name
,
int
xflags
)
{
return
xfs_acl_vremove
(
vp
,
_ACL_TYPE_ACCESS
);
}
STATIC
int
posix_acl_access_get
(
vnode_t
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
return
xfs_acl_vget
(
vp
,
data
,
size
,
_ACL_TYPE_ACCESS
);
}
STATIC
int
posix_acl_access_exists
(
vnode_t
*
vp
)
{
return
xfs_acl_vhasacl_access
(
vp
);
}
STATIC
int
posix_acl_default_set
(
vnode_t
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
return
xfs_acl_vset
(
vp
,
data
,
size
,
_ACL_TYPE_DEFAULT
);
}
STATIC
int
posix_acl_default_get
(
vnode_t
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
return
xfs_acl_vget
(
vp
,
data
,
size
,
_ACL_TYPE_DEFAULT
);
}
STATIC
int
posix_acl_default_remove
(
struct
vnode
*
vp
,
char
*
name
,
int
xflags
)
{
return
xfs_acl_vremove
(
vp
,
_ACL_TYPE_DEFAULT
);
}
STATIC
int
posix_acl_default_exists
(
vnode_t
*
vp
)
{
return
xfs_acl_vhasacl_default
(
vp
);
}
struct
attrnames
posix_acl_access
=
{
.
attr_name
=
"posix_acl_access"
,
.
attr_namelen
=
sizeof
(
"posix_acl_access"
)
-
1
,
.
attr_get
=
posix_acl_access_get
,
.
attr_set
=
posix_acl_access_set
,
.
attr_remove
=
posix_acl_access_remove
,
.
attr_exists
=
posix_acl_access_exists
,
};
struct
attrnames
posix_acl_default
=
{
.
attr_name
=
"posix_acl_default"
,
.
attr_namelen
=
sizeof
(
"posix_acl_default"
)
-
1
,
.
attr_get
=
posix_acl_default_get
,
.
attr_set
=
posix_acl_default_set
,
.
attr_remove
=
posix_acl_default_remove
,
.
attr_exists
=
posix_acl_default_exists
,
};
struct
attrnames
*
attr_system_names
[]
=
{
&
posix_acl_access
,
&
posix_acl_default
};
/*========================================================================
* Namespace-prefix-style attribute name interface routines.
*========================================================================*/
STATIC
int
attr_generic_set
(
struct
vnode
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
int
error
;
VOP_ATTR_SET
(
vp
,
name
,
data
,
size
,
xflags
,
NULL
,
error
);
return
-
error
;
}
STATIC
int
attr_generic_get
(
struct
vnode
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
int
error
,
asize
=
size
;
VOP_ATTR_GET
(
vp
,
name
,
data
,
&
asize
,
xflags
,
NULL
,
error
);
if
(
!
error
)
return
asize
;
return
-
error
;
}
STATIC
int
attr_generic_remove
(
struct
vnode
*
vp
,
char
*
name
,
int
xflags
)
{
int
error
;
VOP_ATTR_REMOVE
(
vp
,
name
,
xflags
,
NULL
,
error
);
return
-
error
;
}
STATIC
int
attr_generic_listadd
(
attrnames_t
*
prefix
,
attrnames_t
*
namesp
,
void
*
data
,
size_t
size
,
ssize_t
*
result
)
{
char
*
p
=
data
+
*
result
;
*
result
+=
prefix
->
attr_namelen
;
*
result
+=
namesp
->
attr_namelen
+
1
;
if
(
!
size
)
return
0
;
if
(
*
result
>
size
)
return
-
ERANGE
;
strcpy
(
p
,
prefix
->
attr_name
);
p
+=
prefix
->
attr_namelen
;
strcpy
(
p
,
namesp
->
attr_name
);
p
+=
namesp
->
attr_namelen
+
1
;
return
0
;
}
STATIC
int
attr_system_list
(
struct
vnode
*
vp
,
void
*
data
,
size_t
size
,
ssize_t
*
result
)
{
attrnames_t
*
namesp
;
int
i
,
error
=
0
;
for
(
i
=
0
;
i
<
ATTR_SYSCOUNT
;
i
++
)
{
namesp
=
attr_system_names
[
i
];
if
(
!
namesp
->
attr_exists
||
!
namesp
->
attr_exists
(
vp
))
continue
;
error
=
attr_generic_listadd
(
&
attr_system
,
namesp
,
data
,
size
,
result
);
if
(
error
)
break
;
}
return
error
;
}
int
attr_generic_list
(
struct
vnode
*
vp
,
void
*
data
,
size_t
size
,
int
xflags
,
ssize_t
*
result
)
{
attrlist_cursor_kern_t
cursor
=
{
0
};
int
error
;
VOP_ATTR_LIST
(
vp
,
data
,
size
,
xflags
,
&
cursor
,
NULL
,
error
);
if
(
error
>
0
)
return
-
error
;
*
result
=
-
error
;
return
attr_system_list
(
vp
,
data
,
size
,
result
);
}
attrnames_t
*
attr_lookup_namespace
(
char
*
name
,
struct
attrnames
**
names
,
int
nnames
)
{
int
i
;
for
(
i
=
0
;
i
<
nnames
;
i
++
)
if
(
!
strncmp
(
name
,
names
[
i
]
->
attr_name
,
names
[
i
]
->
attr_namelen
))
return
names
[
i
];
return
NULL
;
}
/*
* Some checks to prevent people abusing EAs to get over quota:
* - Don't allow modifying user EAs on devices/symlinks;
* - Don't allow modifying user EAs if sticky bit set;
*/
STATIC
int
attr_user_capable
(
struct
vnode
*
vp
,
cred_t
*
cred
)
{
struct
inode
*
inode
=
LINVFS_GET_IP
(
vp
);
if
(
IS_IMMUTABLE
(
inode
)
||
IS_APPEND
(
inode
))
return
-
EPERM
;
if
(
!
S_ISREG
(
inode
->
i_mode
)
&&
!
S_ISDIR
(
inode
->
i_mode
)
&&
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
if
(
S_ISDIR
(
inode
->
i_mode
)
&&
(
inode
->
i_mode
&
S_ISVTX
)
&&
(
current_fsuid
(
cred
)
!=
inode
->
i_uid
)
&&
!
capable
(
CAP_FOWNER
))
return
-
EPERM
;
return
0
;
}
STATIC
int
attr_trusted_capable
(
struct
vnode
*
vp
,
cred_t
*
cred
)
{
struct
inode
*
inode
=
LINVFS_GET_IP
(
vp
);
if
(
IS_IMMUTABLE
(
inode
)
||
IS_APPEND
(
inode
))
return
-
EPERM
;
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
return
0
;
}
STATIC
int
attr_system_set
(
struct
vnode
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
attrnames_t
*
namesp
;
int
error
;
if
(
xflags
&
ATTR_CREATE
)
return
-
EINVAL
;
namesp
=
attr_lookup_namespace
(
name
,
attr_system_names
,
ATTR_SYSCOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
error
=
namesp
->
attr_set
(
vp
,
name
,
data
,
size
,
xflags
);
if
(
!
error
)
error
=
vn_revalidate
(
vp
);
return
error
;
}
STATIC
int
attr_system_get
(
struct
vnode
*
vp
,
char
*
name
,
void
*
data
,
size_t
size
,
int
xflags
)
{
attrnames_t
*
namesp
;
namesp
=
attr_lookup_namespace
(
name
,
attr_system_names
,
ATTR_SYSCOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
return
namesp
->
attr_get
(
vp
,
name
,
data
,
size
,
xflags
);
}
STATIC
int
attr_system_remove
(
struct
vnode
*
vp
,
char
*
name
,
int
xflags
)
{
attrnames_t
*
namesp
;
namesp
=
attr_lookup_namespace
(
name
,
attr_system_names
,
ATTR_SYSCOUNT
);
if
(
!
namesp
)
return
-
EOPNOTSUPP
;
return
namesp
->
attr_remove
(
vp
,
name
,
xflags
);
}
struct
attrnames
attr_system
=
{
.
attr_name
=
"system."
,
.
attr_namelen
=
sizeof
(
"system."
)
-
1
,
.
attr_flag
=
ATTR_SYSTEM
,
.
attr_get
=
attr_system_get
,
.
attr_set
=
attr_system_set
,
.
attr_remove
=
attr_system_remove
,
.
attr_capable
=
(
attrcapable_t
)
fs_noerr
,
};
struct
attrnames
attr_trusted
=
{
.
attr_name
=
"trusted."
,
.
attr_namelen
=
sizeof
(
"trusted."
)
-
1
,
.
attr_flag
=
ATTR_ROOT
,
.
attr_get
=
attr_generic_get
,
.
attr_set
=
attr_generic_set
,
.
attr_remove
=
attr_generic_remove
,
.
attr_capable
=
attr_trusted_capable
,
};
struct
attrnames
attr_user
=
{
.
attr_name
=
"user."
,
.
attr_namelen
=
sizeof
(
"user."
)
-
1
,
.
attr_get
=
attr_generic_get
,
.
attr_set
=
attr_generic_set
,
.
attr_remove
=
attr_generic_remove
,
.
attr_capable
=
attr_user_capable
,
};
struct
attrnames
*
attr_namespaces
[]
=
{
&
attr_system
,
&
attr_trusted
,
&
attr_user
};
fs/xfs/xfs_attr.h
View file @
663be8db
/*
* Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000, 2002
-2003
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -49,9 +49,46 @@
* External interfaces
*========================================================================*/
#define ATTR_ROOT 0x0002
/* use attrs in root namespace, not user */
struct
cred
;
struct
vnode
;
typedef
int
(
*
attrset_t
)(
struct
vnode
*
,
char
*
,
void
*
,
size_t
,
int
);
typedef
int
(
*
attrget_t
)(
struct
vnode
*
,
char
*
,
void
*
,
size_t
,
int
);
typedef
int
(
*
attrremove_t
)(
struct
vnode
*
,
char
*
,
int
);
typedef
int
(
*
attrexists_t
)(
struct
vnode
*
);
typedef
int
(
*
attrcapable_t
)(
struct
vnode
*
,
struct
cred
*
);
typedef
struct
attrnames
{
char
*
attr_name
;
unsigned
int
attr_namelen
;
unsigned
int
attr_flag
;
attrget_t
attr_get
;
attrset_t
attr_set
;
attrremove_t
attr_remove
;
attrexists_t
attr_exists
;
attrcapable_t
attr_capable
;
}
attrnames_t
;
#define ATTR_NAMECOUNT 3
extern
struct
attrnames
attr_user
;
extern
struct
attrnames
attr_system
;
extern
struct
attrnames
attr_trusted
;
extern
struct
attrnames
*
attr_namespaces
[
ATTR_NAMECOUNT
];
#define ATTR_SYSCOUNT 2
extern
struct
attrnames
posix_acl_access
;
extern
struct
attrnames
posix_acl_default
;
extern
struct
attrnames
*
attr_system_names
[
ATTR_SYSCOUNT
];
extern
attrnames_t
*
attr_lookup_namespace
(
char
*
,
attrnames_t
**
,
int
);
extern
int
attr_generic_list
(
struct
vnode
*
,
void
*
,
size_t
,
int
,
ssize_t
*
);
#define ATTR_DONTFOLLOW 0x0001
/* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002
/* use attrs in root (trusted) namespace */
#define ATTR_TRUST 0x0004
/* -- unused, from IRIX -- */
#define ATTR_CREATE 0x0010
/* pure create: fail if attr already exists */
#define ATTR_REPLACE 0x0020
/* pure set: fail if attr does not exist */
#define ATTR_SYSTEM 0x0100
/* use attrs in system (pseudo) namespace */
#define ATTR_KERNOTIME 0x1000
/* [kernel] don't update inode timestamps */
#define ATTR_KERNOVAL 0x2000
/* [kernel] get attr size only, not value */
#define ATTR_KERNAMELS 0x4000
/* [kernel] list attr names (simple list) */
...
...
@@ -126,11 +163,8 @@ typedef struct attrlist_cursor_kern {
* Function prototypes for the kernel.
*========================================================================*/
struct
cred
;
struct
vnode
;
struct
xfs_inode
;
struct
attrlist_cursor_kern
;
struct
xfs_ext_attr
;
struct
xfs_da_args
;
/*
...
...
fs/xfs/xfs_attr_leaf.c
View file @
663be8db
/*
* Copyright (c) 2000-200
2
Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-200
3
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -444,8 +444,10 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
<
context
->
bufsize
)
{
for
(
i
=
0
,
sfe
=
&
sf
->
list
[
0
];
i
<
INT_GET
(
sf
->
hdr
.
count
,
ARCH_CONVERT
);
i
++
)
{
int
ns
=
(
sfe
->
flags
&
XFS_ATTR_ROOT
)
?
ROOT_NAMES
:
USER_NAMES
;
attrnames_t
*
namesp
;
namesp
=
(
sfe
->
flags
&
XFS_ATTR_ROOT
)
?
&
attr_trusted
:
&
attr_user
;
if
(((
context
->
flags
&
ATTR_ROOT
)
!=
0
)
!=
((
sfe
->
flags
&
XFS_ATTR_ROOT
)
!=
0
)
&&
!
(
context
->
flags
&
ATTR_KERNFULLS
))
{
...
...
@@ -454,11 +456,11 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
}
if
(
context
->
flags
&
ATTR_KERNOVAL
)
{
ASSERT
(
context
->
flags
&
ATTR_KERNAMELS
);
context
->
count
+=
xfs_namespaces
[
ns
].
namelen
+
context
->
count
+=
namesp
->
attr_
namelen
+
INT_GET
(
sfe
->
namelen
,
ARCH_CONVERT
)
+
1
;
}
else
{
if
(
xfs_attr_put_listent
(
context
,
n
s
,
if
(
xfs_attr_put_listent
(
context
,
n
amesp
,
(
char
*
)
sfe
->
nameval
,
(
int
)
sfe
->
namelen
,
(
int
)
INT_GET
(
sfe
->
valuelen
,
...
...
@@ -544,18 +546,22 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
* Loop putting entries into the user buffer.
*/
for
(
;
i
<
nsbuf
;
i
++
,
sbp
++
)
{
int
ns
=
(
sbp
->
flags
&
XFS_ATTR_ROOT
)
?
ROOT_NAMES
:
USER_NAMES
;
attrnames_t
*
namesp
;
namesp
=
(
sfe
->
flags
&
XFS_ATTR_ROOT
)
?
&
attr_trusted
:
&
attr_user
;
if
(
cursor
->
hashval
!=
INT_GET
(
sbp
->
hash
,
ARCH_CONVERT
))
{
cursor
->
hashval
=
INT_GET
(
sbp
->
hash
,
ARCH_CONVERT
);
cursor
->
offset
=
0
;
}
if
(
context
->
flags
&
ATTR_KERNOVAL
)
{
ASSERT
(
context
->
flags
&
ATTR_KERNAMELS
);
context
->
count
+=
xfs_namespaces
[
ns
].
namelen
+
sbp
->
namelen
+
1
;
context
->
count
+=
namesp
->
attr_namelen
+
sbp
->
namelen
+
1
;
}
else
{
if
(
xfs_attr_put_listent
(
context
,
n
s
,
if
(
xfs_attr_put_listent
(
context
,
n
amesp
,
sbp
->
name
,
sbp
->
namelen
,
INT_GET
(
sbp
->
valuelen
,
ARCH_CONVERT
)))
break
;
...
...
@@ -2270,7 +2276,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
retval
=
0
;
for
(
;
(
i
<
INT_GET
(
leaf
->
hdr
.
count
,
ARCH_CONVERT
))
&&
(
retval
==
0
);
entry
++
,
i
++
)
{
int
ns
=
(
entry
->
flags
&
XFS_ATTR_ROOT
)
?
ROOT_NAMES
:
USER_NAMES
;
attrnames_t
*
namesp
;
if
(
INT_GET
(
entry
->
hashval
,
ARCH_CONVERT
)
!=
cursor
->
hashval
)
{
cursor
->
hashval
=
INT_GET
(
entry
->
hashval
,
ARCH_CONVERT
);
...
...
@@ -2284,14 +2290,17 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
!
(
context
->
flags
&
ATTR_KERNFULLS
))
continue
;
/* skip non-matching entries */
namesp
=
(
entry
->
flags
&
XFS_ATTR_ROOT
)
?
&
attr_trusted
:
&
attr_user
;
if
(
entry
->
flags
&
XFS_ATTR_LOCAL
)
{
name_loc
=
XFS_ATTR_LEAF_NAME_LOCAL
(
leaf
,
i
);
if
(
context
->
flags
&
ATTR_KERNOVAL
)
{
ASSERT
(
context
->
flags
&
ATTR_KERNAMELS
);
context
->
count
+=
xfs_namespaces
[
ns
].
namelen
+
(
int
)
name_loc
->
namelen
+
1
;
context
->
count
+=
namesp
->
attr_namelen
+
(
int
)
name_loc
->
namelen
+
1
;
}
else
{
retval
=
xfs_attr_put_listent
(
context
,
n
s
,
retval
=
xfs_attr_put_listent
(
context
,
n
amesp
,
(
char
*
)
name_loc
->
nameval
,
(
int
)
name_loc
->
namelen
,
(
int
)
INT_GET
(
name_loc
->
valuelen
,
...
...
@@ -2301,10 +2310,10 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
name_rmt
=
XFS_ATTR_LEAF_NAME_REMOTE
(
leaf
,
i
);
if
(
context
->
flags
&
ATTR_KERNOVAL
)
{
ASSERT
(
context
->
flags
&
ATTR_KERNAMELS
);
context
->
count
+=
xfs_namespaces
[
ns
].
namelen
+
(
int
)
name_rmt
->
namelen
+
1
;
context
->
count
+=
namesp
->
attr_namelen
+
(
int
)
name_rmt
->
namelen
+
1
;
}
else
{
retval
=
xfs_attr_put_listent
(
context
,
n
s
,
retval
=
xfs_attr_put_listent
(
context
,
n
amesp
,
(
char
*
)
name_rmt
->
name
,
(
int
)
name_rmt
->
namelen
,
(
int
)
INT_GET
(
name_rmt
->
valuelen
,
...
...
@@ -2333,7 +2342,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
/*ARGSUSED*/
int
xfs_attr_put_listent
(
xfs_attr_list_context_t
*
context
,
int
ns
,
char
*
name
,
int
namelen
,
int
valuelen
)
attrnames_t
*
namesp
,
char
*
name
,
int
namelen
,
int
valuelen
)
{
attrlist_ent_t
*
aep
;
int
arraytop
;
...
...
@@ -2341,23 +2350,21 @@ xfs_attr_put_listent(xfs_attr_list_context_t *context,
ASSERT
(
!
(
context
->
flags
&
ATTR_KERNOVAL
));
if
(
context
->
flags
&
ATTR_KERNAMELS
)
{
char
*
offset
;
xattr_namespace_t
*
nsp
;
ASSERT
(
context
->
count
>=
0
);
nsp
=
&
xfs_namespaces
[
ns
];
arraytop
=
context
->
count
+
nsp
->
namelen
+
namelen
+
1
;
arraytop
=
context
->
count
+
namesp
->
attr_namelen
+
namelen
+
1
;
if
(
arraytop
>
context
->
firstu
)
{
context
->
count
=
-
1
;
/* insufficient space */
return
(
1
);
}
offset
=
(
char
*
)
context
->
alist
+
context
->
count
;
strncpy
(
offset
,
n
sp
->
name
,
nsp
->
namelen
);
/* namespace */
offset
+=
n
sp
->
namelen
;
strncpy
(
offset
,
n
amesp
->
attr_name
,
namesp
->
attr_namelen
);
offset
+=
n
amesp
->
attr_
namelen
;
strncpy
(
offset
,
name
,
namelen
);
/* real name */
offset
+=
namelen
;
*
offset
=
'\0'
;
context
->
count
+=
n
sp
->
namelen
+
namelen
+
1
;
context
->
count
+=
n
amesp
->
attr_
namelen
+
namelen
+
1
;
return
(
0
);
}
...
...
fs/xfs/xfs_attr_leaf.h
View file @
663be8db
/*
* Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000, 2002
-2003
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -44,6 +44,7 @@
struct
attrlist
;
struct
attrlist_cursor_kern
;
struct
attrnames
;
struct
xfs_dabuf
;
struct
xfs_da_args
;
struct
xfs_da_state
;
...
...
@@ -128,7 +129,7 @@ typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t;
* on the system call, they are "or"ed together for various operations.
*/
#define XFS_ATTR_LOCAL_BIT 0
/* attr is stored locally */
#define XFS_ATTR_ROOT_BIT 1
/* limit access to
attr to userid 0
*/
#define XFS_ATTR_ROOT_BIT 1
/* limit access to
trusted attrs
*/
#define XFS_ATTR_INCOMPLETE_BIT 7
/* attr in middle of create/delete */
#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
...
...
@@ -299,7 +300,8 @@ int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize,
int
*
local
);
int
xfs_attr_leaf_entsize
(
struct
xfs_attr_leafblock
*
leaf
,
int
index
);
int
xfs_attr_put_listent
(
struct
xfs_attr_list_context
*
context
,
int
ns
,
char
*
name
,
int
namelen
,
int
valuelen
);
struct
attrnames
*
,
char
*
name
,
int
namelen
,
int
valuelen
);
int
xfs_attr_rolltrans
(
struct
xfs_trans
**
transp
,
struct
xfs_inode
*
dp
);
#endif
/* __XFS_ATTR_LEAF_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment