99 "io"
1010 "os"
1111 "regexp"
12+ "strings"
1213 "time"
1314
1415 "github.com/containerd/containerd/archive"
@@ -205,7 +206,9 @@ func (r *Registry) unpackLayer(ctx context.Context, layer ocispec.Descriptor, di
205206 if err != nil {
206207 return err
207208 }
208- _ , err = archive .Apply (ctx , dir , decompressed , archive .WithFilter (adjustPerms ))
209+
210+ filters := filterList {adjustPerms , dropXattrs }
211+ _ , err = archive .Apply (ctx , dir , decompressed , archive .WithFilter (filters .and ))
209212
210213 return err
211214}
@@ -217,6 +220,19 @@ func ensureNamespace(ctx context.Context) context.Context {
217220 return ctx
218221}
219222
223+ type filterList []archive.Filter
224+
225+ func (f filterList ) and (h * tar.Header ) (bool , error ) {
226+ for _ , filter := range f {
227+ ok , err := filter (h )
228+ if ! ok || err != nil {
229+ return ok , err
230+ }
231+ }
232+
233+ return true , nil
234+ }
235+
220236func adjustPerms (h * tar.Header ) (bool , error ) {
221237 h .Uid = os .Getuid ()
222238 h .Gid = os .Getgid ()
@@ -229,3 +245,19 @@ func adjustPerms(h *tar.Header) (bool, error) {
229245
230246 return true , nil
231247}
248+
249+ // paxSchilyXattr contains the key prefix for xattrs stored in PAXRecords (see https://golang.org/src/archive/tar/common.go for more details).
250+ const paxSchilyXattr = "SCHILY.xattr."
251+
252+ // dropXattrs removes all xattrs from a Header.
253+ // This is useful for unpacking on systems where writing certain xattrs is a restricted operation; e.g. "security.capability" on SELinux.
254+ func dropXattrs (h * tar.Header ) (bool , error ) {
255+ h .Xattrs = nil // Deprecated, but still in use, clear anyway.
256+ for key := range h .PAXRecords {
257+ if strings .HasPrefix (key , paxSchilyXattr ) { // Xattrs are stored under keys with the "Schilly.xattr." prefix.
258+ delete (h .PAXRecords , key )
259+ }
260+ }
261+
262+ return true , nil
263+ }
0 commit comments