/
optical_drive.go
111 lines (96 loc) · 3.28 KB
/
optical_drive.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
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2016-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 (
"fmt"
"github.com/snapcore/snapd/interfaces"
"github.com/snapcore/snapd/interfaces/apparmor"
"github.com/snapcore/snapd/snap"
)
const opticalDriveSummary = `allows access to optical drives`
const opticalDriveBaseDeclarationSlots = `
optical-drive:
allow-installation:
slot-snap-type:
- core
deny-connection:
plug-attributes:
write: true
deny-auto-connection:
plug-attributes:
write: true
`
const opticalDriveConnectedPlugAppArmor = `
# Allow read access to optical drives
/dev/sr[0-9]* r,
/dev/scd[0-9]* r,
# allow all generic scsi devices here and use the device cgroup to
# differentiate optical drives
/dev/sg[0-9]* r,
@{PROC}/sys/dev/cdrom/info r,
/run/udev/data/b11:[0-9]* r,
`
var opticalDriveConnectedPlugUDev = []string{
`KERNEL=="sr[0-9]*"`,
`KERNEL=="scd[0-9]*"`,
// ATTRS{type} below takes scsi peripheral device types.
// Type 4 is 'Write-once device'; type 5 is 'CD/DVD-ROM device'
// ref: https://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
`SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5"`,
}
// opticalDriveInterface is the type for optical drive interfaces.
type opticalDriveInterface struct {
commonInterface
}
// BeforePrepareSlot checks and possibly modifies a slot.
// Valid "optical-drive" slots may contain the attribute "write".
// If defined, the attribute "write" must be either "true" or "false".
func (iface *opticalDriveInterface) BeforePreparePlug(plug *snap.PlugInfo) error {
// It's fine if 'write' isn't specified, but if it is, it needs to be bool
if w, ok := plug.Attrs["write"]; ok {
_, ok = w.(bool)
if !ok {
return fmt.Errorf(`optical-drive "write" attribute must be a boolean`)
}
}
return nil
}
func (iface *opticalDriveInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
var write bool
_ = plug.Attr("write", &write)
// Add the common readonly policy
spec.AddSnippet(opticalDriveConnectedPlugAppArmor)
// 'write: true' grants write access to the devices
if write {
spec.AddSnippet("# Allow write access to optical drives")
spec.AddSnippet("/dev/sr[0-9]* w,")
spec.AddSnippet("/dev/scd[0-9]* w,")
spec.AddSnippet("/dev/sg[0-9]* w,")
}
return nil
}
func init() {
registerIface(&opticalDriveInterface{commonInterface: commonInterface{
name: "optical-drive",
summary: opticalDriveSummary,
implicitOnCore: false,
implicitOnClassic: true,
baseDeclarationSlots: opticalDriveBaseDeclarationSlots,
connectedPlugUDev: opticalDriveConnectedPlugUDev,
}})
}