forked from snapcore/snapd
/
account_control.go
126 lines (105 loc) · 3.38 KB
/
account_control.go
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
114
115
116
117
118
119
120
121
122
123
124
125
126
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package builtin
import (
"strconv"
"strings"
"github.com/snapcore/snapd/interfaces"
"github.com/snapcore/snapd/interfaces/seccomp"
"github.com/snapcore/snapd/osutil"
)
const accountControlSummary = `allows managing non-system user accounts`
const accountControlBaseDeclarationSlots = `
account-control:
allow-installation:
slot-snap-type:
- core
deny-auto-connection: true
`
const accountControlConnectedPlugAppArmor = `
/{,usr/}sbin/chpasswd ixr,
/{,usr/}sbin/user{add,del} ixr,
# Allow modifying the non-system extrausers NSS database. The extrausers
# database is used on Ubuntu Core devices to manage both privileged and
# unprivileged users (since /etc/passwd, /etc/group, etc are all read-only).
/var/lib/extrausers/ r,
/var/lib/extrausers/** rwkl,
# Needed by useradd
/etc/login.defs r,
/etc/default/useradd r,
/etc/default/nss r,
/etc/pam.d/{,*} r,
# Needed by chpasswd
/{,usr/}lib/@{multiarch}/security/* ixr,
# Useradd needs netlink
network netlink raw,
# Capabilities needed by useradd
capability audit_write,
capability chown,
capability fsetid,
# useradd writes the result in the log
#include <abstractions/wutmp>
/var/log/faillog rwk,
`
// Needed because useradd uses a netlink socket, {{group}} is used as a
// placeholder argument for the actual ID of a group owning /etc/shadow
const accountControlConnectedPlugSecCompTemplate = `
# useradd requires chowning to 0:'{{group}}'
fchown - u:root {{group}}
fchown32 - u:root {{group}}
# from libaudit1
bind
socket AF_NETLINK - NETLINK_AUDIT
`
type accountControlInterface struct {
commonInterface
secCompSnippet string
}
func makeAccountControlSecCompSnippet() (string, error) {
gid, err := osutil.FindGidOwning("/etc/shadow")
if err != nil {
return "", err
}
snippet := strings.Replace(accountControlConnectedPlugSecCompTemplate,
"{{group}}", strconv.FormatUint(gid, 10), -1)
return snippet, nil
}
func (iface *accountControlInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
if iface.secCompSnippet == "" {
// Cache the snippet after it's successfully computed once
snippet, err := makeAccountControlSecCompSnippet()
if err != nil {
return err
}
iface.secCompSnippet = snippet
}
spec.AddSnippet(iface.secCompSnippet)
return nil
}
func init() {
registerIface(&accountControlInterface{commonInterface: commonInterface{
name: "account-control",
summary: accountControlSummary,
implicitOnCore: true,
implicitOnClassic: true,
baseDeclarationSlots: accountControlBaseDeclarationSlots,
connectedPlugAppArmor: accountControlConnectedPlugAppArmor,
// handled by SecCompConnectedPlug
connectedPlugSecComp: "",
}})
}