blob: 7227ffe51eacd3bb61120bf06e21840eac09c672 [file] [log] [blame]
Dan Walshc7d749e2012-03-16 11:05:17 -04001/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Joshua Brindle13cd4c82008-08-19 15:30:36 -04002#include <unistd.h>
3#include <sys/types.h>
4#include <stdlib.h>
5#include <errno.h>
6#include "selinux_internal.h"
Dan Walsh9c46a0a2011-10-20 15:14:08 -04007#include <selinux/avc.h>
Stephen Smalley7bdc38c2014-07-08 14:03:39 -04008#include "avc_internal.h"
Joshua Brindle13cd4c82008-08-19 15:30:36 -04009
Dan Walsh9c46a0a2011-10-20 15:14:08 -040010static pthread_once_t once = PTHREAD_ONCE_INIT;
Stephen Smalley2fa21cc2012-09-14 13:55:43 -040011static int selinux_enabled;
Dan Walsh9c46a0a2011-10-20 15:14:08 -040012
13static void avc_init_once(void)
14{
Stephen Smalley2fa21cc2012-09-14 13:55:43 -040015 selinux_enabled = is_selinux_enabled();
Stephen Smalleyb408d722015-09-18 16:03:24 -040016 if (selinux_enabled == 1) {
17 if (avc_open(NULL, 0))
18 return;
Stephen Smalleyb408d722015-09-18 16:03:24 -040019 }
Dan Walsh9c46a0a2011-10-20 15:14:08 -040020}
21
Stephen Smalley9eb9c932014-02-19 09:16:17 -050022int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
Dan Walshc7d749e2012-03-16 11:05:17 -040023 int rc;
Dan Walsh9c46a0a2011-10-20 15:14:08 -040024 security_id_t scon_id;
25 security_id_t tcon_id;
26 security_class_t sclass;
27 access_vector_t av;
28
Dan Walsh9c46a0a2011-10-20 15:14:08 -040029 __selinux_once(once, avc_init_once);
30
Stephen Smalley2fa21cc2012-09-14 13:55:43 -040031 if (selinux_enabled != 1)
32 return 0;
33
Dan Walshc7d749e2012-03-16 11:05:17 -040034 rc = avc_context_to_sid(scon, &scon_id);
35 if (rc < 0)
36 return rc;
Dan Walsh9c46a0a2011-10-20 15:14:08 -040037
Stephen Smalleyb408d722015-09-18 16:03:24 -040038 rc = avc_context_to_sid(tcon, &tcon_id);
39 if (rc < 0)
40 return rc;
41
42 (void) avc_netlink_check_nb();
Dan Walsh9c46a0a2011-10-20 15:14:08 -040043
Dan Walshc7d749e2012-03-16 11:05:17 -040044 sclass = string_to_security_class(class);
45 if (sclass == 0) {
46 rc = errno;
Stephen Smalley7bdc38c2014-07-08 14:03:39 -040047 avc_log(SELINUX_ERROR, "Unknown class %s", class);
Dan Walshc7d749e2012-03-16 11:05:17 -040048 if (security_deny_unknown() == 0)
49 return 0;
50 errno = rc;
51 return -1;
52 }
Dan Walsh9c46a0a2011-10-20 15:14:08 -040053
Dan Walshc7d749e2012-03-16 11:05:17 -040054 av = string_to_av_perm(sclass, perm);
55 if (av == 0) {
56 rc = errno;
Stephen Smalley7bdc38c2014-07-08 14:03:39 -040057 avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
Dan Walshc7d749e2012-03-16 11:05:17 -040058 if (security_deny_unknown() == 0)
59 return 0;
60 errno = rc;
61 return -1;
62 }
Dan Walsh9c46a0a2011-10-20 15:14:08 -040063
Dan Walshc7d749e2012-03-16 11:05:17 -040064 return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
Dan Walsh9c46a0a2011-10-20 15:14:08 -040065}
66
Joshua Brindle13cd4c82008-08-19 15:30:36 -040067int selinux_check_passwd_access(access_vector_t requested)
68{
69 int status = -1;
Stephen Smalley9eb9c932014-02-19 09:16:17 -050070 char *user_context;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040071 if (is_selinux_enabled() == 0)
72 return 0;
73 if (getprevcon_raw(&user_context) == 0) {
74 security_class_t passwd_class;
75 struct av_decision avd;
76 int retval;
77
78 passwd_class = string_to_security_class("passwd");
Petr Lautrbach5d592842019-02-06 21:33:50 +010079 if (passwd_class == 0) {
80 freecon(user_context);
Joshua Brindle13cd4c82008-08-19 15:30:36 -040081 return 0;
Petr Lautrbach5d592842019-02-06 21:33:50 +010082 }
Joshua Brindle13cd4c82008-08-19 15:30:36 -040083
84 retval = security_compute_av_raw(user_context,
85 user_context,
86 passwd_class,
87 requested,
88 &avd);
89
90 if ((retval == 0) && ((requested & avd.allowed) == requested)) {
91 status = 0;
92 }
93 freecon(user_context);
94 }
95
96 if (status != 0 && security_getenforce() == 0)
97 status = 0;
98
99 return status;
100}
101
102hidden_def(selinux_check_passwd_access)
103
104int checkPasswdAccess(access_vector_t requested)
105{
106 return selinux_check_passwd_access(requested);
107}