-
Notifications
You must be signed in to change notification settings - Fork 1
/
applyFilters.go
146 lines (135 loc) · 4.39 KB
/
applyFilters.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package filters
import (
"os"
"strconv"
api "github.com/polydawn/go-timeless-api"
"github.com/polydawn/go-timeless-api/rio"
"github.com/polydawn/rio/fs"
"github.com/warpfork/go-errcat"
)
var (
myUid = uint32(os.Getuid())
myGid = uint32(os.Getgid())
)
/*
ApplyPackFilter mutates the given fs.Metadata to be filtered.
An error is returned if any of of the metadata is matched by filters
set to "reject".
The fmeta.Type will be set to fs.Type_Invalid in the case of a node which
is matched by filters set to "ignore" if the filter is for a critical
property of the node (e.g. "dev=ignore" will trigger this; whereas
"sticky=ignore" will simply strip the sticky bit from the perm bits).
This means you should just skip creation of this node entirely.
Note that if the filter has any fields which are set of "unspecified",
they will be ignored; you should probably check `IsComplete` on the filter
before calling this. (We don't do it inside of here because you're
probably using this in a loop of large cardinality.)
*/
func ApplyPackFilter(ff api.FilesetPackFilter, fmeta *fs.Metadata) error {
if keep, setTo := ff.Uid(); !keep {
fmeta.Uid = uint32(setTo)
}
if keep, setTo := ff.Gid(); !keep {
fmeta.Gid = uint32(setTo)
}
if keep, setTo := ff.Mtime(); !keep {
fmeta.Mtime = setTo
}
if keep := ff.Sticky(); !keep {
fmeta.Perms &= ^fs.Perms_Sticky
}
if keep, reject := ff.Setid(); reject {
if fmeta.Perms&(fs.Perms_Setuid|fs.Perms_Setgid) != 0 {
return errcat.ErrorDetailed(
rio.ErrFilterRejection,
"filter rejection: setid bits",
map[string]string{
"path": fmeta.Name.String(),
"perms": "0" + strconv.FormatUint(uint64(fmeta.Perms), 8),
},
)
}
} else if !keep {
fmeta.Perms &= ^(fs.Perms_Setuid | fs.Perms_Setgid)
}
if keep, reject := ff.Dev(); reject {
if fmeta.Type == fs.Type_Device || fmeta.Type == fs.Type_CharDevice {
return errcat.ErrorDetailed(
rio.ErrFilterRejection,
"filter rejection: device node",
map[string]string{
"path": fmeta.Name.String(),
"type": string(fmeta.Type),
"majmin": strconv.FormatInt(fmeta.Devmajor, 10) + "," + strconv.FormatInt(fmeta.Devminor, 10),
},
)
}
} else if !keep {
fmeta.Type = fs.Type_Invalid
}
return nil
}
/*
ApplyUnpackFilter mutates the given fs.Metadata to be filtered.
An error is returned if any of of the metadata is matched by filters
set to "reject".
The fmeta.Type will be set to fs.Type_Invalid in the case of a node which
is matched by filters set to "ignore" if the filter is for a critical
property of the node (e.g. "dev=ignore" will trigger this; whereas
"sticky=ignore" will simply strip the sticky bit from the perm bits).
This means you should just skip creation of this node entirely.
Note that if the filter has any fields which are set of "unspecified",
they will be ignored; you should probably check `IsComplete` on the filter
before calling this. (We don't do it inside of here because you're
probably using this in a loop of large cardinality.)
*/
func ApplyUnpackFilter(ff api.FilesetUnpackFilter, fmeta *fs.Metadata) error {
if follow, mine, setTo := ff.Uid(); mine {
fmeta.Uid = myUid
} else if !follow {
fmeta.Uid = uint32(setTo)
}
if follow, mine, setTo := ff.Gid(); mine {
fmeta.Gid = myGid
} else if !follow {
fmeta.Gid = uint32(setTo)
}
if follow, now, setTo := ff.Mtime(); now {
panic("unpack filter mtime=now not yet supported")
} else if !follow {
fmeta.Mtime = setTo
}
if follow := ff.Sticky(); !follow {
fmeta.Perms &= ^fs.Perms_Sticky
}
if follow, reject := ff.Setid(); reject {
if fmeta.Perms&(fs.Perms_Setuid|fs.Perms_Setgid) != 0 {
return errcat.ErrorDetailed(
rio.ErrFilterRejection,
"filter rejection: setid bits",
map[string]string{
"path": fmeta.Name.String(),
"perms": "0" + strconv.FormatUint(uint64(fmeta.Perms), 8),
},
)
}
} else if !follow {
fmeta.Perms &= ^(fs.Perms_Setuid | fs.Perms_Setgid)
}
if follow, reject := ff.Dev(); reject {
if fmeta.Type == fs.Type_Device || fmeta.Type == fs.Type_CharDevice {
return errcat.ErrorDetailed(
rio.ErrFilterRejection,
"filter rejection: device node",
map[string]string{
"path": fmeta.Name.String(),
"type": string(fmeta.Type),
"majmin": strconv.FormatInt(fmeta.Devmajor, 10) + "," + strconv.FormatInt(fmeta.Devminor, 10),
},
)
}
} else if !follow {
fmeta.Type = fs.Type_Invalid
}
return nil
}