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