github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/interfaces/builtin/account_control.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package builtin 21 22 import ( 23 "strconv" 24 "strings" 25 26 "github.com/snapcore/snapd/interfaces" 27 "github.com/snapcore/snapd/interfaces/seccomp" 28 "github.com/snapcore/snapd/osutil" 29 ) 30 31 const accountControlSummary = `allows managing non-system user accounts` 32 33 const accountControlBaseDeclarationSlots = ` 34 account-control: 35 allow-installation: 36 slot-snap-type: 37 - core 38 deny-auto-connection: true 39 ` 40 41 const accountControlConnectedPlugAppArmor = ` 42 /{,usr/}sbin/chpasswd ixr, 43 /{,usr/}sbin/user{add,del} ixr, 44 45 # Allow modifying the non-system extrausers NSS database. The extrausers 46 # database is used on Ubuntu Core devices to manage both privileged and 47 # unprivileged users (since /etc/passwd, /etc/group, etc are all read-only). 48 /var/lib/extrausers/ r, 49 /var/lib/extrausers/** rwkl, 50 51 # Needed by useradd 52 /etc/login.defs r, 53 /etc/default/useradd r, 54 /etc/default/nss r, 55 /etc/pam.d/{,*} r, 56 57 # Needed by chpasswd 58 /{,usr/}lib/@{multiarch}/security/* ixr, 59 60 # Useradd needs netlink 61 network netlink raw, 62 63 # Capabilities needed by useradd 64 capability audit_write, 65 capability chown, 66 capability fsetid, 67 68 # useradd writes the result in the log 69 #include <abstractions/wutmp> 70 /var/log/faillog rwk, 71 ` 72 73 // Needed because useradd uses a netlink socket, {{group}} is used as a 74 // placeholder argument for the actual ID of a group owning /etc/shadow 75 const accountControlConnectedPlugSecCompTemplate = ` 76 # useradd requires chowning to 0:'{{group}}' 77 fchown - u:root {{group}} 78 fchown32 - u:root {{group}} 79 80 # from libaudit1 81 bind 82 socket AF_NETLINK - NETLINK_AUDIT 83 ` 84 85 type accountControlInterface struct { 86 commonInterface 87 secCompSnippet string 88 } 89 90 func makeAccountControlSecCompSnippet() (string, error) { 91 gid, err := osutil.FindGidOwning("/etc/shadow") 92 if err != nil { 93 return "", err 94 } 95 96 snippet := strings.Replace(accountControlConnectedPlugSecCompTemplate, 97 "{{group}}", strconv.FormatUint(gid, 10), -1) 98 99 return snippet, nil 100 } 101 102 func (iface *accountControlInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 103 if iface.secCompSnippet == "" { 104 // Cache the snippet after it's successfully computed once 105 snippet, err := makeAccountControlSecCompSnippet() 106 if err != nil { 107 return err 108 } 109 iface.secCompSnippet = snippet 110 } 111 spec.AddSnippet(iface.secCompSnippet) 112 return nil 113 } 114 115 func init() { 116 registerIface(&accountControlInterface{commonInterface: commonInterface{ 117 name: "account-control", 118 summary: accountControlSummary, 119 implicitOnCore: true, 120 implicitOnClassic: true, 121 baseDeclarationSlots: accountControlBaseDeclarationSlots, 122 connectedPlugAppArmor: accountControlConnectedPlugAppArmor, 123 // handled by SecCompConnectedPlug 124 connectedPlugSecComp: "", 125 }}) 126 }