mirror of
https://github.com/octoleo/restic.git
synced 2024-11-22 12:55:18 +00:00
Add support for extended attributes on symlinks
Linux allows the use of non-`user.` extended attributes on symlinks. One of the main users of this functionality is SELinux's `security.selinux` xattr for storing a path's label. By storing symlink xattrs, restic is now suitable for backing up the root filesystem on Linux distributions that use SELinux. This commit adds support for symlink xattrs when backing up data, restoring data, and mounting snapshots via a fuse mount. All calls to the xattr library have been updated to the use `L` variants of the various functions, which always operate on the path given, without following symlinks. Fixes: #4375 Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
parent
74ca82a6f8
commit
8c02ebb029
8
changelog/unreleased/issue-4375
Normal file
8
changelog/unreleased/issue-4375
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Enhancement: Add support for extended attributes on symlinks
|
||||||
|
|
||||||
|
Restic now supports extended attributes on symlinks when backing up,
|
||||||
|
restoring, or FUSE-mounting snapshots. This includes, for example, the
|
||||||
|
`security.selinux` xattr on Linux distributions that use SELinux.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/4375
|
||||||
|
https://github.com/restic/restic/pull/4379
|
@ -6,6 +6,8 @@ package fuse
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/restic/restic/internal/debug"
|
||||||
|
|
||||||
"github.com/anacrolix/fuse"
|
"github.com/anacrolix/fuse"
|
||||||
"github.com/anacrolix/fuse/fs"
|
"github.com/anacrolix/fuse/fs"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
@ -46,3 +48,21 @@ func (l *link) Attr(_ context.Context, a *fuse.Attr) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *link) Listxattr(_ context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
|
||||||
|
debug.Log("Listxattr(%v, %v)", l.node.Name, req.Size)
|
||||||
|
for _, attr := range l.node.ExtendedAttributes {
|
||||||
|
resp.Append(attr.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *link) Getxattr(_ context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
|
||||||
|
debug.Log("Getxattr(%v, %v, %v)", l.node.Name, req.Name, req.Size)
|
||||||
|
attrval := l.node.GetExtendedAttribute(req.Name)
|
||||||
|
if attrval != nil {
|
||||||
|
resp.Xattr = attrval
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fuse.ErrNoXattr
|
||||||
|
}
|
||||||
|
@ -609,10 +609,6 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (node *Node) fillExtendedAttributes(path string) error {
|
func (node *Node) fillExtendedAttributes(path string) error {
|
||||||
if node.Type == "symlink" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
xattrs, err := Listxattr(path)
|
xattrs, err := Listxattr(path)
|
||||||
debug.Log("fillExtendedAttributes(%v) %v %v", path, xattrs, err)
|
debug.Log("fillExtendedAttributes(%v) %v %v", path, xattrs, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,20 +13,20 @@ import (
|
|||||||
|
|
||||||
// Getxattr retrieves extended attribute data associated with path.
|
// Getxattr retrieves extended attribute data associated with path.
|
||||||
func Getxattr(path, name string) ([]byte, error) {
|
func Getxattr(path, name string) ([]byte, error) {
|
||||||
b, err := xattr.Get(path, name)
|
b, err := xattr.LGet(path, name)
|
||||||
return b, handleXattrErr(err)
|
return b, handleXattrErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listxattr retrieves a list of names of extended attributes associated with the
|
// Listxattr retrieves a list of names of extended attributes associated with the
|
||||||
// given path in the file system.
|
// given path in the file system.
|
||||||
func Listxattr(path string) ([]string, error) {
|
func Listxattr(path string) ([]string, error) {
|
||||||
l, err := xattr.List(path)
|
l, err := xattr.LList(path)
|
||||||
return l, handleXattrErr(err)
|
return l, handleXattrErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setxattr associates name and data together as an attribute of path.
|
// Setxattr associates name and data together as an attribute of path.
|
||||||
func Setxattr(path, name string, data []byte) error {
|
func Setxattr(path, name string, data []byte) error {
|
||||||
return handleXattrErr(xattr.Set(path, name, data))
|
return handleXattrErr(xattr.LSet(path, name, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleXattrErr(err error) error {
|
func handleXattrErr(err error) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user