2019-05-31 01:09:32 -07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2005-04-16 15:20:36 -07:00
|
|
|
/*
|
|
|
|
* An access vector table (avtab) is a hash table
|
|
|
|
* of access vectors and transition types indexed
|
|
|
|
* by a type pair and a class. An access vector
|
|
|
|
* table is used to represent the type enforcement
|
|
|
|
* tables.
|
|
|
|
*
|
2023-07-19 11:12:50 -04:00
|
|
|
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
|
2005-04-16 15:20:36 -07:00
|
|
|
*/
|
|
|
|
|
2024-02-22 18:52:19 -05:00
|
|
|
/* Updated: Frank Mayer <mayerf@tresys.com> and
|
|
|
|
* Karl MacMillan <kmacmillan@tresys.com>
|
|
|
|
* Added conditional policy language extensions
|
|
|
|
* Copyright (C) 2003 Tresys Technology, LLC
|
2007-08-24 11:55:11 +09:00
|
|
|
*
|
|
|
|
* Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
|
2024-02-22 18:52:19 -05:00
|
|
|
* Tuned number of hash slots for avtab to reduce memory usage
|
2005-04-16 15:20:36 -07:00
|
|
|
*/
|
2024-02-22 18:52:19 -05:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
#ifndef _SS_AVTAB_H_
|
|
|
|
#define _SS_AVTAB_H_
|
|
|
|
|
2015-07-10 17:19:56 -04:00
|
|
|
#include "security.h"
|
2015-03-24 16:54:16 -04:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
struct avtab_key {
|
2024-02-22 18:52:19 -05:00
|
|
|
u16 source_type; /* source type */
|
|
|
|
u16 target_type; /* target type */
|
|
|
|
u16 target_class; /* target object class */
|
|
|
|
#define AVTAB_ALLOWED 0x0001
|
|
|
|
#define AVTAB_AUDITALLOW 0x0002
|
|
|
|
#define AVTAB_AUDITDENY 0x0004
|
|
|
|
#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
|
|
|
|
#define AVTAB_TRANSITION 0x0010
|
|
|
|
#define AVTAB_MEMBER 0x0020
|
|
|
|
#define AVTAB_CHANGE 0x0040
|
|
|
|
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
|
2015-07-10 17:19:56 -04:00
|
|
|
/* extended permissions */
|
|
|
|
#define AVTAB_XPERMS_ALLOWED 0x0100
|
2024-02-22 18:52:19 -05:00
|
|
|
#define AVTAB_XPERMS_AUDITALLOW 0x0200
|
2015-07-10 17:19:56 -04:00
|
|
|
#define AVTAB_XPERMS_DONTAUDIT 0x0400
|
2024-02-22 18:52:19 -05:00
|
|
|
#define AVTAB_XPERMS \
|
|
|
|
(AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | \
|
|
|
|
AVTAB_XPERMS_DONTAUDIT)
|
|
|
|
#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
|
|
|
|
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
|
|
|
|
u16 specified; /* what field is specified */
|
2005-09-03 15:55:16 -07:00
|
|
|
};
|
|
|
|
|
2015-07-10 17:19:56 -04:00
|
|
|
/*
|
|
|
|
* For operations that require more than the 32 permissions provided by the avc
|
|
|
|
* extended permissions may be used to provide 256 bits of permissions.
|
|
|
|
*/
|
|
|
|
struct avtab_extended_perms {
|
|
|
|
/* These are not flags. All 256 values may be used */
|
selinux: Add netlink xperm support
Reuse the existing extended permissions infrastructure to support
policies based on the netlink message types.
A new policy capability "netlink_xperm" is introduced. When disabled,
the previous behaviour is preserved. That is, netlink_send will rely on
the permission mappings defined in nlmsgtab.c (e.g, nlmsg_read for
RTM_GETADDR on NETLINK_ROUTE). When enabled, the mappings are ignored
and the generic "nlmsg" permission is used instead.
The new "nlmsg" permission is an extended permission. The 16 bits of the
extended permission are mapped to the nlmsg_type field.
Example policy on Android, preventing regular apps from accessing the
device's MAC address and ARP table, but allowing this access to
privileged apps, looks as follows:
allow netdomain self:netlink_route_socket {
create read getattr write setattr lock append connect getopt
setopt shutdown nlmsg
};
allowxperm netdomain self:netlink_route_socket nlmsg ~{
RTM_GETLINK RTM_GETNEIGH RTM_GETNEIGHTBL
};
allowxperm priv_app self:netlink_route_socket nlmsg {
RTM_GETLINK RTM_GETNEIGH RTM_GETNEIGHTBL
};
The constants in the example above (e.g., RTM_GETLINK) are explicitly
defined in the policy.
It is possible to generate policies to support kernels that may or
may not have the capability enabled by generating a rule for each
scenario. For instance:
allow domain self:netlink_audit_socket nlmsg_read;
allow domain self:netlink_audit_socket nlmsg;
allowxperm domain self:netlink_audit_socket nlmsg { AUDIT_GET };
The approach of defining a new permission ("nlmsg") instead of relying
on the existing permissions (e.g., "nlmsg_read", "nlmsg_readpriv" or
"nlmsg_tty_audit") has been preferred because:
1. This is similar to the other extended permission ("ioctl");
2. With the new extended permission, the coarse-grained mapping is not
necessary anymore. It could eventually be removed, which would be
impossible if the extended permission was defined below these.
3. Having a single extra extended permission considerably simplifies
the implementation here and in libselinux.
Signed-off-by: Thiébaud Weksteen <tweek@google.com>
Signed-off-by: Bram Bonné <brambonne@google.com>
[PM: manual merge fixes for sock_skip_has_perm()]
Signed-off-by: Paul Moore <paul@paul-moore.com>
2024-09-12 11:45:03 +10:00
|
|
|
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
|
|
|
|
#define AVTAB_XPERMS_IOCTLDRIVER 0x02
|
|
|
|
#define AVTAB_XPERMS_NLMSG 0x03
|
2015-07-10 17:19:56 -04:00
|
|
|
/* extension of the avtab_key specified */
|
|
|
|
u8 specified; /* ioctl, netfilter, ... */
|
|
|
|
/*
|
|
|
|
* if 256 bits is not adequate as is often the case with ioctls, then
|
|
|
|
* multiple extended perms may be used and the driver field
|
|
|
|
* specifies which permissions are included.
|
|
|
|
*/
|
|
|
|
u8 driver;
|
|
|
|
/* 256 bits of permissions */
|
|
|
|
struct extended_perms_data perms;
|
|
|
|
};
|
|
|
|
|
2005-09-03 15:55:16 -07:00
|
|
|
struct avtab_datum {
|
2015-07-10 17:19:56 -04:00
|
|
|
union {
|
|
|
|
u32 data; /* access vector or type value */
|
|
|
|
struct avtab_extended_perms *xperms;
|
|
|
|
} u;
|
2005-04-16 15:20:36 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct avtab_node {
|
|
|
|
struct avtab_key key;
|
|
|
|
struct avtab_datum datum;
|
|
|
|
struct avtab_node *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct avtab {
|
2019-03-11 23:31:10 -07:00
|
|
|
struct avtab_node **htable;
|
2024-02-22 18:52:19 -05:00
|
|
|
u32 nel; /* number of elements */
|
|
|
|
u32 nslot; /* number of hash slots */
|
|
|
|
u32 mask; /* mask to compute hash func */
|
2005-04-16 15:20:36 -07:00
|
|
|
};
|
|
|
|
|
2020-03-05 14:55:43 -05:00
|
|
|
void avtab_init(struct avtab *h);
|
2024-12-16 17:40:01 +01:00
|
|
|
int avtab_alloc(struct avtab *h, u32 nrules);
|
selinux: fix cond_list corruption when changing booleans
Currently, duplicate_policydb_cond_list() first copies the whole
conditional avtab and then tries to link to the correct entries in
cond_dup_av_list() using avtab_search(). However, since the conditional
avtab may contain multiple entries with the same key, this approach
often fails to find the right entry, potentially leading to wrong rules
being activated/deactivated when booleans are changed.
To fix this, instead start with an empty conditional avtab and add the
individual entries one-by-one while building the new av_lists. This
approach leads to the correct result, since each entry is present in the
av_lists exactly once.
The issue can be reproduced with Fedora policy as follows:
# sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A
allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True
allow ftpd_t public_content_rw_t:dir { add_name create link remove_name rename reparent rmdir setattr unlink watch watch_reads write }; [ ftpd_anon_write ]:True
# setsebool ftpd_anon_write=off ftpd_connect_all_unreserved=off ftpd_connect_db=off ftpd_full_access=off
On fixed kernels, the sesearch output is the same after the setsebool
command:
# sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A
allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True
allow ftpd_t public_content_rw_t:dir { add_name create link remove_name rename reparent rmdir setattr unlink watch watch_reads write }; [ ftpd_anon_write ]:True
While on the broken kernels, it will be different:
# sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A
allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True
allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True
allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True
While there, also simplify the computation of nslots. This changes the
nslots values for nrules 2 or 3 to just two slots instead of 4, which
makes the sequence more consistent.
Cc: stable@vger.kernel.org
Fixes: c7c556f1e81b ("selinux: refactor changing booleans")
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
2021-04-02 10:56:19 +02:00
|
|
|
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
|
2005-04-16 15:20:36 -07:00
|
|
|
void avtab_destroy(struct avtab *h);
|
2023-07-28 17:19:31 +02:00
|
|
|
|
2024-02-22 18:52:19 -05:00
|
|
|
#define MAX_AVTAB_HASH_BITS 16
|
|
|
|
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
|
|
|
|
|
2023-07-28 17:19:31 +02:00
|
|
|
#ifdef CONFIG_SECURITY_SELINUX_DEBUG
|
2023-04-20 17:05:02 +02:00
|
|
|
void avtab_hash_eval(struct avtab *h, const char *tag);
|
2023-07-28 17:19:31 +02:00
|
|
|
#else
|
|
|
|
static inline void avtab_hash_eval(struct avtab *h, const char *tag)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2007-11-07 10:08:00 -05:00
|
|
|
struct policydb;
|
2024-12-16 17:40:05 +01:00
|
|
|
struct policy_file;
|
|
|
|
int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *pol,
|
2021-03-30 15:16:46 +02:00
|
|
|
int (*insert)(struct avtab *a, const struct avtab_key *k,
|
|
|
|
const struct avtab_datum *d, void *p),
|
2024-10-23 17:27:10 +02:00
|
|
|
void *p, bool conditional);
|
2005-09-03 15:55:16 -07:00
|
|
|
|
2024-12-16 17:40:05 +01:00
|
|
|
int avtab_read(struct avtab *a, struct policy_file *fp, struct policydb *pol);
|
2024-02-22 18:52:19 -05:00
|
|
|
int avtab_write_item(struct policydb *p, const struct avtab_node *cur,
|
2024-12-16 17:40:05 +01:00
|
|
|
struct policy_file *fp);
|
|
|
|
int avtab_write(struct policydb *p, struct avtab *a, struct policy_file *fp);
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2021-03-30 15:16:46 +02:00
|
|
|
struct avtab_node *avtab_insert_nonunique(struct avtab *h,
|
|
|
|
const struct avtab_key *key,
|
|
|
|
const struct avtab_datum *datum);
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2021-03-30 15:16:46 +02:00
|
|
|
struct avtab_node *avtab_search_node(struct avtab *h,
|
|
|
|
const struct avtab_key *key);
|
2024-02-22 18:52:19 -05:00
|
|
|
struct avtab_node *avtab_search_node_next(struct avtab_node *node,
|
|
|
|
u16 specified);
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2024-02-22 18:52:19 -05:00
|
|
|
#endif /* _SS_AVTAB_H_ */
|