1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# Copyright: (c) 2021, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import sys
from ansible.module_utils.common.text.converters import to_native, to_bytes
from ctypes import CDLL, c_char_p, c_int, byref, POINTER, get_errno
try:
_selinux_lib = CDLL('libselinux.so.1', use_errno=True)
except OSError:
raise ImportError('unable to load libselinux.so')
def _module_setup():
def _check_rc(rc):
if rc < 0:
errno = get_errno()
raise OSError(errno, os.strerror(errno))
return rc
binary_char_type = type(b'')
class _to_char_p:
@classmethod
def from_param(cls, strvalue):
if strvalue is not None and not isinstance(strvalue, binary_char_type):
strvalue = to_bytes(strvalue)
return strvalue
# FIXME: swap restype to errcheck
_funcmap = dict(
is_selinux_enabled={},
is_selinux_mls_enabled={},
lgetfilecon_raw=dict(argtypes=[_to_char_p, POINTER(c_char_p)], restype=_check_rc),
# NB: matchpathcon is deprecated and should be rewritten on selabel_lookup (but will be a PITA)
matchpathcon=dict(argtypes=[_to_char_p, c_int, POINTER(c_char_p)], restype=_check_rc),
security_policyvers={},
selinux_getenforcemode=dict(argtypes=[POINTER(c_int)]),
security_getenforce={},
lsetfilecon=dict(argtypes=[_to_char_p, _to_char_p], restype=_check_rc),
selinux_getpolicytype=dict(argtypes=[POINTER(c_char_p)], restype=_check_rc),
)
_thismod = sys.modules[__name__]
for fname, cfg in _funcmap.items():
fn = getattr(_selinux_lib, fname, None)
if not fn:
raise ImportError('missing selinux function: {0}'.format(fname))
# all ctypes pointers share the same base type
base_ptr_type = type(POINTER(c_int))
fn.argtypes = cfg.get('argtypes', None)
fn.restype = cfg.get('restype', c_int)
# just patch simple directly callable functions directly onto the module
if not fn.argtypes or not any(argtype for argtype in fn.argtypes if type(argtype) == base_ptr_type):
setattr(_thismod, fname, fn)
continue
# NB: this validation code must run after all the wrappers have been declared
unimplemented_funcs = set(_funcmap).difference(dir(_thismod))
if unimplemented_funcs:
raise NotImplementedError('implementation is missing functions: {0}'.format(unimplemented_funcs))
# begin wrapper function impls
def selinux_getenforcemode():
enforcemode = c_int()
rc = _selinux_lib.selinux_getenforcemode(byref(enforcemode))
return [rc, enforcemode.value]
def selinux_getpolicytype():
con = c_char_p()
try:
rc = _selinux_lib.selinux_getpolicytype(byref(con))
return [rc, to_native(con.value)]
finally:
_selinux_lib.freecon(con)
def lgetfilecon_raw(path):
con = c_char_p()
try:
rc = _selinux_lib.lgetfilecon_raw(path, byref(con))
return [rc, to_native(con.value)]
finally:
_selinux_lib.freecon(con)
def matchpathcon(path, mode):
con = c_char_p()
try:
rc = _selinux_lib.matchpathcon(path, mode, byref(con))
return [rc, to_native(con.value)]
finally:
_selinux_lib.freecon(con)
_module_setup()
del _module_setup
# end wrapper function impls
|