⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs4acl.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct posix_ace_state group;	struct posix_ace_state other;	struct posix_ace_state everyone;	struct posix_ace_state mask; /* Deny unused in this case */	struct posix_ace_state_array *users;	struct posix_ace_state_array *groups;};static intinit_state(struct posix_acl_state *state, int cnt){	int alloc;	memset(state, 0, sizeof(struct posix_acl_state));	state->empty = 1;	/*	 * In the worst case, each individual acl could be for a distinct	 * named user or group, but we don't no which, so we allocate	 * enough space for either:	 */	alloc = sizeof(struct posix_ace_state_array)		+ cnt*sizeof(struct posix_ace_state);	state->users = kzalloc(alloc, GFP_KERNEL);	if (!state->users)		return -ENOMEM;	state->groups = kzalloc(alloc, GFP_KERNEL);	if (!state->groups) {		kfree(state->users);		return -ENOMEM;	}	return 0;}static voidfree_state(struct posix_acl_state *state) {	kfree(state->users);	kfree(state->groups);}static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate){	state->mask.allow |= astate->allow;}/* * Certain bits (SYNCHRONIZE, DELETE, WRITE_OWNER, READ/WRITE_NAMED_ATTRS, * READ_ATTRIBUTES, READ_ACL) are currently unenforceable and don't translate * to traditional read/write/execute permissions. * * It's problematic to reject acls that use certain mode bits, because it * places the burden on users to learn the rules about which bits one * particular server sets, without giving the user a lot of help--we return an * error that could mean any number of different things.  To make matters * worse, the problematic bits might be introduced by some application that's * automatically mapping from some other acl model. * * So wherever possible we accept anything, possibly erring on the side of * denying more permissions than necessary. * * However we do reject *explicit* DENY's of a few bits representing * permissions we could never deny: */static inline int check_deny(u32 mask, int isowner){	if (mask & (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL))		return -EINVAL;	if (!isowner)		return 0;	if (mask & (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL))		return -EINVAL;	return 0;}static struct posix_acl *posix_state_to_acl(struct posix_acl_state *state, unsigned int flags){	struct posix_acl_entry *pace;	struct posix_acl *pacl;	int nace;	int i, error = 0;	/*	 * ACLs with no ACEs are treated differently in the inheritable	 * and effective cases: when there are no inheritable ACEs, we	 * set a zero-length default posix acl:	 */	if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {		pacl = posix_acl_alloc(0, GFP_KERNEL);		return pacl ? pacl : ERR_PTR(-ENOMEM);	}	/*	 * When there are no effective ACEs, the following will end	 * up setting a 3-element effective posix ACL with all	 * permissions zero.	 */	nace = 4 + state->users->n + state->groups->n;	pacl = posix_acl_alloc(nace, GFP_KERNEL);	if (!pacl)		return ERR_PTR(-ENOMEM);	pace = pacl->a_entries;	pace->e_tag = ACL_USER_OBJ;	error = check_deny(state->owner.deny, 1);	if (error)		goto out_err;	low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);	pace->e_id = ACL_UNDEFINED_ID;	for (i=0; i < state->users->n; i++) {		pace++;		pace->e_tag = ACL_USER;		error = check_deny(state->users->aces[i].perms.deny, 0);		if (error)			goto out_err;		low_mode_from_nfs4(state->users->aces[i].perms.allow,					&pace->e_perm, flags);		pace->e_id = state->users->aces[i].uid;		add_to_mask(state, &state->users->aces[i].perms);	}	pace++;	pace->e_tag = ACL_GROUP_OBJ;	error = check_deny(state->group.deny, 0);	if (error)		goto out_err;	low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);	pace->e_id = ACL_UNDEFINED_ID;	add_to_mask(state, &state->group);	for (i=0; i < state->groups->n; i++) {		pace++;		pace->e_tag = ACL_GROUP;		error = check_deny(state->groups->aces[i].perms.deny, 0);		if (error)			goto out_err;		low_mode_from_nfs4(state->groups->aces[i].perms.allow,					&pace->e_perm, flags);		pace->e_id = state->groups->aces[i].uid;		add_to_mask(state, &state->groups->aces[i].perms);	}	pace++;	pace->e_tag = ACL_MASK;	low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);	pace->e_id = ACL_UNDEFINED_ID;	pace++;	pace->e_tag = ACL_OTHER;	error = check_deny(state->other.deny, 0);	if (error)		goto out_err;	low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);	pace->e_id = ACL_UNDEFINED_ID;	return pacl;out_err:	posix_acl_release(pacl);	return ERR_PTR(error);}static inline void allow_bits(struct posix_ace_state *astate, u32 mask){	/* Allow all bits in the mask not already denied: */	astate->allow |= mask & ~astate->deny;}static inline void deny_bits(struct posix_ace_state *astate, u32 mask){	/* Deny all bits in the mask not already allowed: */	astate->deny |= mask & ~astate->allow;}static int find_uid(struct posix_acl_state *state, struct posix_ace_state_array *a, uid_t uid){	int i;	for (i = 0; i < a->n; i++)		if (a->aces[i].uid == uid)			return i;	/* Not found: */	a->n++;	a->aces[i].uid = uid;	a->aces[i].perms.allow = state->everyone.allow;	a->aces[i].perms.deny  = state->everyone.deny;	return i;}static void deny_bits_array(struct posix_ace_state_array *a, u32 mask){	int i;	for (i=0; i < a->n; i++)		deny_bits(&a->aces[i].perms, mask);}static void allow_bits_array(struct posix_ace_state_array *a, u32 mask){	int i;	for (i=0; i < a->n; i++)		allow_bits(&a->aces[i].perms, mask);}static void process_one_v4_ace(struct posix_acl_state *state,				struct nfs4_ace *ace){	u32 mask = ace->access_mask;	int i;	state->empty = 0;	switch (ace2type(ace)) {	case ACL_USER_OBJ:		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {			allow_bits(&state->owner, mask);		} else {			deny_bits(&state->owner, mask);		}		break;	case ACL_USER:		i = find_uid(state, state->users, ace->who);		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {			allow_bits(&state->users->aces[i].perms, mask);		} else {			deny_bits(&state->users->aces[i].perms, mask);			mask = state->users->aces[i].perms.deny;			deny_bits(&state->owner, mask);		}		break;	case ACL_GROUP_OBJ:		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {			allow_bits(&state->group, mask);		} else {			deny_bits(&state->group, mask);			mask = state->group.deny;			deny_bits(&state->owner, mask);			deny_bits(&state->everyone, mask);			deny_bits_array(state->users, mask);			deny_bits_array(state->groups, mask);		}		break;	case ACL_GROUP:		i = find_uid(state, state->groups, ace->who);		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {			allow_bits(&state->groups->aces[i].perms, mask);		} else {			deny_bits(&state->groups->aces[i].perms, mask);			mask = state->groups->aces[i].perms.deny;			deny_bits(&state->owner, mask);			deny_bits(&state->group, mask);			deny_bits(&state->everyone, mask);			deny_bits_array(state->users, mask);			deny_bits_array(state->groups, mask);		}		break;	case ACL_OTHER:		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {			allow_bits(&state->owner, mask);			allow_bits(&state->group, mask);			allow_bits(&state->other, mask);			allow_bits(&state->everyone, mask);			allow_bits_array(state->users, mask);			allow_bits_array(state->groups, mask);		} else {			deny_bits(&state->owner, mask);			deny_bits(&state->group, mask);			deny_bits(&state->other, mask);			deny_bits(&state->everyone, mask);			deny_bits_array(state->users, mask);			deny_bits_array(state->groups, mask);		}	}}int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,			    struct posix_acl **dpacl, unsigned int flags){	struct posix_acl_state effective_acl_state, default_acl_state;	struct nfs4_ace *ace;	int ret;	ret = init_state(&effective_acl_state, acl->naces);	if (ret)		return ret;	ret = init_state(&default_acl_state, acl->naces);	if (ret)		goto out_estate;	ret = -EINVAL;	for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&		    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)			goto out_dstate;		if (ace->flag & ~NFS4_SUPPORTED_FLAGS)			goto out_dstate;		if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {			process_one_v4_ace(&effective_acl_state, ace);			continue;		}		if (!(flags & NFS4_ACL_DIR))			goto out_dstate;		/*		 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT		 * is set, we're effectively turning on the other.  That's OK,		 * according to rfc 3530.		 */		process_one_v4_ace(&default_acl_state, ace);		if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))			process_one_v4_ace(&effective_acl_state, ace);	}	*pacl = posix_state_to_acl(&effective_acl_state, flags);	if (IS_ERR(*pacl)) {		ret = PTR_ERR(*pacl);		*pacl = NULL;		goto out_dstate;	}	*dpacl = posix_state_to_acl(&default_acl_state,						flags | NFS4_ACL_TYPE_DEFAULT);	if (IS_ERR(*dpacl)) {		ret = PTR_ERR(*dpacl);		*dpacl = NULL;		posix_acl_release(*pacl);		*pacl = NULL;		goto out_dstate;	}	sort_pacl(*pacl);	sort_pacl(*dpacl);	ret = 0;out_dstate:	free_state(&default_acl_state);out_estate:	free_state(&effective_acl_state);	return ret;}static shortace2type(struct nfs4_ace *ace){	switch (ace->whotype) {		case NFS4_ACL_WHO_NAMED:			return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?					ACL_GROUP : ACL_USER);		case NFS4_ACL_WHO_OWNER:			return ACL_USER_OBJ;		case NFS4_ACL_WHO_GROUP:			return ACL_GROUP_OBJ;		case NFS4_ACL_WHO_EVERYONE:			return ACL_OTHER;	}	BUG();	return -1;}EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);struct nfs4_acl *nfs4_acl_new(int n){	struct nfs4_acl *acl;	acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);	if (acl == NULL)		return NULL;	acl->naces = 0;	return acl;}static struct {	char *string;	int   stringlen;	int type;} s2t_map[] = {	{		.string    = "OWNER@",		.stringlen = sizeof("OWNER@") - 1,		.type      = NFS4_ACL_WHO_OWNER,	},	{		.string    = "GROUP@",		.stringlen = sizeof("GROUP@") - 1,		.type      = NFS4_ACL_WHO_GROUP,	},	{		.string    = "EVERYONE@",		.stringlen = sizeof("EVERYONE@") - 1,		.type      = NFS4_ACL_WHO_EVERYONE,	},};intnfs4_acl_get_whotype(char *p, u32 len){	int i;	for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {		if (s2t_map[i].stringlen == len &&				0 == memcmp(s2t_map[i].string, p, len))			return s2t_map[i].type;	}	return NFS4_ACL_WHO_NAMED;}intnfs4_acl_write_who(int who, char *p){	int i;	for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {		if (s2t_map[i].type == who) {			memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);			return s2t_map[i].stringlen;		}	}	BUG();	return -1;}EXPORT_SYMBOL(nfs4_acl_new);EXPORT_SYMBOL(nfs4_acl_get_whotype);EXPORT_SYMBOL(nfs4_acl_write_who);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -