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
nexedi
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
Show 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
);
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
;
}
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
;
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