xref: /freebsd/sys/cddl/compat/opensolaris/kern/opensolaris_acl.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
10970b4baSEdward Tomasz Napierala /*-
20970b4baSEdward Tomasz Napierala  * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
30970b4baSEdward Tomasz Napierala  *
40970b4baSEdward Tomasz Napierala  * Redistribution and use in source and binary forms, with or without
50970b4baSEdward Tomasz Napierala  * modification, are permitted provided that the following conditions
60970b4baSEdward Tomasz Napierala  * are met:
70970b4baSEdward Tomasz Napierala  * 1. Redistributions of source code must retain the above copyright
80970b4baSEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer.
90970b4baSEdward Tomasz Napierala  * 2. Redistributions in binary form must reproduce the above copyright
100970b4baSEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer in the
110970b4baSEdward Tomasz Napierala  *    documentation and/or other materials provided with the distribution.
120970b4baSEdward Tomasz Napierala  *
13b7014134SEdward Tomasz Napierala  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14b7014134SEdward Tomasz Napierala  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15b7014134SEdward Tomasz Napierala  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16b7014134SEdward Tomasz Napierala  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17b7014134SEdward Tomasz Napierala  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18b7014134SEdward Tomasz Napierala  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19b7014134SEdward Tomasz Napierala  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20b7014134SEdward Tomasz Napierala  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21b7014134SEdward Tomasz Napierala  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22b7014134SEdward Tomasz Napierala  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23b7014134SEdward Tomasz Napierala  * SUCH DAMAGE.
240970b4baSEdward Tomasz Napierala  */
250970b4baSEdward Tomasz Napierala 
260970b4baSEdward Tomasz Napierala #include <sys/param.h>
270970b4baSEdward Tomasz Napierala #include <sys/systm.h>
280970b4baSEdward Tomasz Napierala #include <sys/types.h>
290970b4baSEdward Tomasz Napierala #include <sys/malloc.h>
300970b4baSEdward Tomasz Napierala #include <sys/errno.h>
310970b4baSEdward Tomasz Napierala #include <sys/zfs_acl.h>
320970b4baSEdward Tomasz Napierala #include <sys/acl.h>
330970b4baSEdward Tomasz Napierala 
340970b4baSEdward Tomasz Napierala struct zfs2bsd {
350970b4baSEdward Tomasz Napierala 	uint32_t	zb_zfs;
360970b4baSEdward Tomasz Napierala 	int		zb_bsd;
370970b4baSEdward Tomasz Napierala };
380970b4baSEdward Tomasz Napierala 
390970b4baSEdward Tomasz Napierala struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA},
400970b4baSEdward Tomasz Napierala 			{ACE_WRITE_DATA, ACL_WRITE_DATA},
410970b4baSEdward Tomasz Napierala 			{ACE_EXECUTE, ACL_EXECUTE},
420970b4baSEdward Tomasz Napierala 			{ACE_APPEND_DATA, ACL_APPEND_DATA},
430970b4baSEdward Tomasz Napierala 			{ACE_DELETE_CHILD, ACL_DELETE_CHILD},
440970b4baSEdward Tomasz Napierala 			{ACE_DELETE, ACL_DELETE},
450970b4baSEdward Tomasz Napierala 			{ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
460970b4baSEdward Tomasz Napierala 			{ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
470970b4baSEdward Tomasz Napierala 			{ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
480970b4baSEdward Tomasz Napierala 			{ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
490970b4baSEdward Tomasz Napierala 			{ACE_READ_ACL, ACL_READ_ACL},
500970b4baSEdward Tomasz Napierala 			{ACE_WRITE_ACL, ACL_WRITE_ACL},
510970b4baSEdward Tomasz Napierala 			{ACE_WRITE_OWNER, ACL_WRITE_OWNER},
520970b4baSEdward Tomasz Napierala 			{ACE_SYNCHRONIZE, ACL_SYNCHRONIZE},
530970b4baSEdward Tomasz Napierala 			{0, 0}};
540970b4baSEdward Tomasz Napierala 
550970b4baSEdward Tomasz Napierala struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE,
560970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_FILE_INHERIT},
570970b4baSEdward Tomasz Napierala 			{ACE_DIRECTORY_INHERIT_ACE,
580970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_DIRECTORY_INHERIT},
590970b4baSEdward Tomasz Napierala 			{ACE_NO_PROPAGATE_INHERIT_ACE,
600970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_NO_PROPAGATE_INHERIT},
610970b4baSEdward Tomasz Napierala 			{ACE_INHERIT_ONLY_ACE,
620970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_INHERIT_ONLY},
63*28ffe927SXin LI 			{ACE_INHERITED_ACE,
64*28ffe927SXin LI 			    ACL_ENTRY_INHERITED},
650970b4baSEdward Tomasz Napierala 			{ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
660970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_SUCCESSFUL_ACCESS},
670970b4baSEdward Tomasz Napierala 			{ACE_FAILED_ACCESS_ACE_FLAG,
680970b4baSEdward Tomasz Napierala 			    ACL_ENTRY_FAILED_ACCESS},
690970b4baSEdward Tomasz Napierala 			{0, 0}};
700970b4baSEdward Tomasz Napierala 
710970b4baSEdward Tomasz Napierala static int
_bsd_from_zfs(uint32_t zfs,const struct zfs2bsd * table)720970b4baSEdward Tomasz Napierala _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table)
730970b4baSEdward Tomasz Napierala {
740970b4baSEdward Tomasz Napierala 	const struct zfs2bsd *tmp;
750970b4baSEdward Tomasz Napierala 	int bsd = 0;
760970b4baSEdward Tomasz Napierala 
770970b4baSEdward Tomasz Napierala 	for (tmp = table; tmp->zb_zfs != 0; tmp++) {
780970b4baSEdward Tomasz Napierala 		if (zfs & tmp->zb_zfs)
790970b4baSEdward Tomasz Napierala 			bsd |= tmp->zb_bsd;
800970b4baSEdward Tomasz Napierala 	}
810970b4baSEdward Tomasz Napierala 
820970b4baSEdward Tomasz Napierala 	return (bsd);
830970b4baSEdward Tomasz Napierala }
840970b4baSEdward Tomasz Napierala 
850970b4baSEdward Tomasz Napierala static uint32_t
_zfs_from_bsd(int bsd,const struct zfs2bsd * table)860970b4baSEdward Tomasz Napierala _zfs_from_bsd(int bsd, const struct zfs2bsd *table)
870970b4baSEdward Tomasz Napierala {
880970b4baSEdward Tomasz Napierala 	const struct zfs2bsd *tmp;
890970b4baSEdward Tomasz Napierala 	uint32_t zfs = 0;
900970b4baSEdward Tomasz Napierala 
910970b4baSEdward Tomasz Napierala 	for (tmp = table; tmp->zb_bsd != 0; tmp++) {
920970b4baSEdward Tomasz Napierala 		if (bsd & tmp->zb_bsd)
930970b4baSEdward Tomasz Napierala 			zfs |= tmp->zb_zfs;
940970b4baSEdward Tomasz Napierala 	}
950970b4baSEdward Tomasz Napierala 
960970b4baSEdward Tomasz Napierala 	return (zfs);
970970b4baSEdward Tomasz Napierala }
980970b4baSEdward Tomasz Napierala 
990970b4baSEdward Tomasz Napierala int
acl_from_aces(struct acl * aclp,const ace_t * aces,int nentries)1000970b4baSEdward Tomasz Napierala acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries)
1010970b4baSEdward Tomasz Napierala {
1020970b4baSEdward Tomasz Napierala 	int i;
1030970b4baSEdward Tomasz Napierala 	struct acl_entry *entry;
1040970b4baSEdward Tomasz Napierala 	const ace_t *ace;
1050970b4baSEdward Tomasz Napierala 
106de2a5732SEdward Tomasz Napierala 	if (nentries < 1) {
107de2a5732SEdward Tomasz Napierala 		printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n");
108de2a5732SEdward Tomasz Napierala 		return (EINVAL);
109de2a5732SEdward Tomasz Napierala 	}
1100970b4baSEdward Tomasz Napierala 
1110970b4baSEdward Tomasz Napierala 	if (nentries > ACL_MAX_ENTRIES) {
1120970b4baSEdward Tomasz Napierala 		/*
1130970b4baSEdward Tomasz Napierala 		 * I believe it may happen only when moving a pool
1140970b4baSEdward Tomasz Napierala 		 * from SunOS to FreeBSD.
1150970b4baSEdward Tomasz Napierala 		 */
1160970b4baSEdward Tomasz Napierala 		printf("acl_from_aces: ZFS ACL too big to fit "
1170970b4baSEdward Tomasz Napierala 		    "into 'struct acl'; returning EINVAL.\n");
1180970b4baSEdward Tomasz Napierala 		return (EINVAL);
1190970b4baSEdward Tomasz Napierala 	}
1200970b4baSEdward Tomasz Napierala 
1210970b4baSEdward Tomasz Napierala 	bzero(aclp, sizeof(*aclp));
1220970b4baSEdward Tomasz Napierala 	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
1230970b4baSEdward Tomasz Napierala 	aclp->acl_cnt = nentries;
1240970b4baSEdward Tomasz Napierala 
1250970b4baSEdward Tomasz Napierala 	for (i = 0; i < nentries; i++) {
1260970b4baSEdward Tomasz Napierala 		entry = &(aclp->acl_entry[i]);
1270970b4baSEdward Tomasz Napierala 		ace = &(aces[i]);
1280970b4baSEdward Tomasz Napierala 
1290970b4baSEdward Tomasz Napierala 		if (ace->a_flags & ACE_OWNER)
1300970b4baSEdward Tomasz Napierala 			entry->ae_tag = ACL_USER_OBJ;
1310970b4baSEdward Tomasz Napierala 		else if (ace->a_flags & ACE_GROUP)
1320970b4baSEdward Tomasz Napierala 			entry->ae_tag = ACL_GROUP_OBJ;
1330970b4baSEdward Tomasz Napierala 		else if (ace->a_flags & ACE_EVERYONE)
1340970b4baSEdward Tomasz Napierala 			entry->ae_tag = ACL_EVERYONE;
1350970b4baSEdward Tomasz Napierala 		else if (ace->a_flags & ACE_IDENTIFIER_GROUP)
1360970b4baSEdward Tomasz Napierala 			entry->ae_tag = ACL_GROUP;
1370970b4baSEdward Tomasz Napierala 		else
1380970b4baSEdward Tomasz Napierala 			entry->ae_tag = ACL_USER;
1390970b4baSEdward Tomasz Napierala 
1400970b4baSEdward Tomasz Napierala 		if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP)
1410970b4baSEdward Tomasz Napierala 			entry->ae_id = ace->a_who;
1420970b4baSEdward Tomasz Napierala 		else
1430970b4baSEdward Tomasz Napierala 			entry->ae_id = ACL_UNDEFINED_ID;
1440970b4baSEdward Tomasz Napierala 
1450970b4baSEdward Tomasz Napierala 		entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms);
1460970b4baSEdward Tomasz Napierala 		entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags);
1470970b4baSEdward Tomasz Napierala 
1480970b4baSEdward Tomasz Napierala 		switch (ace->a_type) {
1490970b4baSEdward Tomasz Napierala 		case ACE_ACCESS_ALLOWED_ACE_TYPE:
1500970b4baSEdward Tomasz Napierala 			entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
1510970b4baSEdward Tomasz Napierala 			break;
1520970b4baSEdward Tomasz Napierala 		case ACE_ACCESS_DENIED_ACE_TYPE:
1530970b4baSEdward Tomasz Napierala 			entry->ae_entry_type = ACL_ENTRY_TYPE_DENY;
1540970b4baSEdward Tomasz Napierala 			break;
1550970b4baSEdward Tomasz Napierala 		case ACE_SYSTEM_AUDIT_ACE_TYPE:
1560970b4baSEdward Tomasz Napierala 			entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
1570970b4baSEdward Tomasz Napierala 			break;
1580970b4baSEdward Tomasz Napierala 		case ACE_SYSTEM_ALARM_ACE_TYPE:
1590970b4baSEdward Tomasz Napierala 			entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
1600970b4baSEdward Tomasz Napierala 			break;
1610970b4baSEdward Tomasz Napierala 		default:
1620970b4baSEdward Tomasz Napierala 			panic("acl_from_aces: a_type is 0x%x", ace->a_type);
1630970b4baSEdward Tomasz Napierala 		}
1640970b4baSEdward Tomasz Napierala 	}
1650970b4baSEdward Tomasz Napierala 
1660970b4baSEdward Tomasz Napierala 	return (0);
1670970b4baSEdward Tomasz Napierala }
1680970b4baSEdward Tomasz Napierala 
1690970b4baSEdward Tomasz Napierala void
aces_from_acl(ace_t * aces,int * nentries,const struct acl * aclp)1700970b4baSEdward Tomasz Napierala aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp)
1710970b4baSEdward Tomasz Napierala {
1720970b4baSEdward Tomasz Napierala 	int i;
1730970b4baSEdward Tomasz Napierala 	const struct acl_entry *entry;
1740970b4baSEdward Tomasz Napierala 	ace_t *ace;
1750970b4baSEdward Tomasz Napierala 
1760970b4baSEdward Tomasz Napierala 	bzero(aces, sizeof(*aces) * aclp->acl_cnt);
1770970b4baSEdward Tomasz Napierala 
1780970b4baSEdward Tomasz Napierala 	*nentries = aclp->acl_cnt;
1790970b4baSEdward Tomasz Napierala 
1800970b4baSEdward Tomasz Napierala 	for (i = 0; i < aclp->acl_cnt; i++) {
1810970b4baSEdward Tomasz Napierala 		entry = &(aclp->acl_entry[i]);
1820970b4baSEdward Tomasz Napierala 		ace = &(aces[i]);
1830970b4baSEdward Tomasz Napierala 
1840970b4baSEdward Tomasz Napierala 		ace->a_who = entry->ae_id;
1850970b4baSEdward Tomasz Napierala 
1860970b4baSEdward Tomasz Napierala 		if (entry->ae_tag == ACL_USER_OBJ)
1870970b4baSEdward Tomasz Napierala 			ace->a_flags = ACE_OWNER;
1880970b4baSEdward Tomasz Napierala 		else if (entry->ae_tag == ACL_GROUP_OBJ)
1890970b4baSEdward Tomasz Napierala 			ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP);
1900970b4baSEdward Tomasz Napierala 		else if (entry->ae_tag == ACL_GROUP)
1910970b4baSEdward Tomasz Napierala 			ace->a_flags = ACE_IDENTIFIER_GROUP;
1920970b4baSEdward Tomasz Napierala 		else if (entry->ae_tag == ACL_EVERYONE)
1930970b4baSEdward Tomasz Napierala 			ace->a_flags = ACE_EVERYONE;
1940970b4baSEdward Tomasz Napierala 		else /* ACL_USER */
1950970b4baSEdward Tomasz Napierala 			ace->a_flags = 0;
1960970b4baSEdward Tomasz Napierala 
1970970b4baSEdward Tomasz Napierala 		ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms);
1980970b4baSEdward Tomasz Napierala 		ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags);
1990970b4baSEdward Tomasz Napierala 
2000970b4baSEdward Tomasz Napierala 		switch (entry->ae_entry_type) {
2010970b4baSEdward Tomasz Napierala 		case ACL_ENTRY_TYPE_ALLOW:
2020970b4baSEdward Tomasz Napierala 			ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
2030970b4baSEdward Tomasz Napierala 			break;
2040970b4baSEdward Tomasz Napierala 		case ACL_ENTRY_TYPE_DENY:
2050970b4baSEdward Tomasz Napierala 			ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
2060970b4baSEdward Tomasz Napierala 			break;
2070970b4baSEdward Tomasz Napierala 		case ACL_ENTRY_TYPE_ALARM:
2080970b4baSEdward Tomasz Napierala 			ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
2090970b4baSEdward Tomasz Napierala 			break;
2100970b4baSEdward Tomasz Napierala 		case ACL_ENTRY_TYPE_AUDIT:
2110970b4baSEdward Tomasz Napierala 			ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
2120970b4baSEdward Tomasz Napierala 			break;
2130970b4baSEdward Tomasz Napierala 		default:
2140970b4baSEdward Tomasz Napierala 			panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type);
2150970b4baSEdward Tomasz Napierala 		}
2160970b4baSEdward Tomasz Napierala 	}
2170970b4baSEdward Tomasz Napierala }
218