Skip to content

Commit 66c8503

Browse files
authored
Merge pull request #169 from rhatdan/lgetfile
Add LFileLabel and LSetFileLabel
2 parents 0cb05ae + 1b18907 commit 66c8503

File tree

4 files changed

+99
-5
lines changed

4 files changed

+99
-5
lines changed

go-selinux/selinux.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,30 @@ func ClassIndex(class string) (int, error) {
6161
return classIndex(class)
6262
}
6363

64-
// SetFileLabel sets the SELinux label for this path or returns an error.
64+
// SetFileLabel sets the SELinux label for this path, following symlinks,
65+
// or returns an error.
6566
func SetFileLabel(fpath string, label string) error {
6667
return setFileLabel(fpath, label)
6768
}
6869

69-
// FileLabel returns the SELinux label for this path or returns an error.
70+
// LsetFileLabel sets the SELinux label for this path, not following symlinks,
71+
// or returns an error.
72+
func LsetFileLabel(fpath string, label string) error {
73+
return lSetFileLabel(fpath, label)
74+
}
75+
76+
// FileLabel returns the SELinux label for this path, following symlinks,
77+
// or returns an error.
7078
func FileLabel(fpath string) (string, error) {
7179
return fileLabel(fpath)
7280
}
7381

82+
// LfileLabel returns the SELinux label for this path, not following symlinks,
83+
// or returns an error.
84+
func LfileLabel(fpath string) (string, error) {
85+
return lFileLabel(fpath)
86+
}
87+
7488
// SetFSCreateLabel tells the kernel what label to use for all file system objects
7589
// created by this task.
7690
// Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel

go-selinux/selinux_linux.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ func classIndex(class string) (int, error) {
316316
return index, nil
317317
}
318318

319-
// setFileLabel sets the SELinux label for this path or returns an error.
320-
func setFileLabel(fpath string, label string) error {
319+
// lSetFileLabel sets the SELinux label for this path, not following symlinks,
320+
// or returns an error.
321+
func lSetFileLabel(fpath string, label string) error {
321322
if fpath == "" {
322323
return ErrEmptyPath
323324
}
@@ -334,12 +335,50 @@ func setFileLabel(fpath string, label string) error {
334335
return nil
335336
}
336337

337-
// fileLabel returns the SELinux label for this path or returns an error.
338+
// setFileLabel sets the SELinux label for this path, following symlinks,
339+
// or returns an error.
340+
func setFileLabel(fpath string, label string) error {
341+
if fpath == "" {
342+
return ErrEmptyPath
343+
}
344+
for {
345+
err := unix.Setxattr(fpath, xattrNameSelinux, []byte(label), 0)
346+
if err == nil {
347+
break
348+
}
349+
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
350+
return &os.PathError{Op: "setxattr", Path: fpath, Err: err}
351+
}
352+
}
353+
354+
return nil
355+
}
356+
357+
// fileLabel returns the SELinux label for this path, following symlinks,
358+
// or returns an error.
338359
func fileLabel(fpath string) (string, error) {
339360
if fpath == "" {
340361
return "", ErrEmptyPath
341362
}
342363

364+
label, err := getxattr(fpath, xattrNameSelinux)
365+
if err != nil {
366+
return "", &os.PathError{Op: "getxattr", Path: fpath, Err: err}
367+
}
368+
// Trim the NUL byte at the end of the byte buffer, if present.
369+
if len(label) > 0 && label[len(label)-1] == '\x00' {
370+
label = label[:len(label)-1]
371+
}
372+
return string(label), nil
373+
}
374+
375+
// lFileLabel returns the SELinux label for this path, not following symlinks,
376+
// or returns an error.
377+
func lFileLabel(fpath string) (string, error) {
378+
if fpath == "" {
379+
return "", ErrEmptyPath
380+
}
381+
343382
label, err := lgetxattr(fpath, xattrNameSelinux)
344383
if err != nil {
345384
return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}

go-selinux/selinux_stub.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@ func setFileLabel(fpath string, label string) error {
1717
return nil
1818
}
1919

20+
func lSetFileLabel(fpath string, label string) error {
21+
return nil
22+
}
23+
2024
func fileLabel(fpath string) (string, error) {
2125
return "", nil
2226
}
2327

28+
func lFileLabel(fpath string) (string, error) {
29+
return "", nil
30+
}
31+
2432
func setFSCreateLabel(label string) error {
2533
return nil
2634
}

go-selinux/xattrs_linux.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,36 @@ func doLgetxattr(path, attr string, dest []byte) (int, error) {
3636
}
3737
}
3838
}
39+
40+
// getxattr returns a []byte slice containing the value of
41+
// an extended attribute attr set for path.
42+
func getxattr(path, attr string) ([]byte, error) {
43+
// Start with a 128 length byte array
44+
dest := make([]byte, 128)
45+
sz, errno := dogetxattr(path, attr, dest)
46+
for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
47+
// Buffer too small, use zero-sized buffer to get the actual size
48+
sz, errno = dogetxattr(path, attr, []byte{})
49+
if errno != nil {
50+
return nil, errno
51+
}
52+
53+
dest = make([]byte, sz)
54+
sz, errno = dogetxattr(path, attr, dest)
55+
}
56+
if errno != nil {
57+
return nil, errno
58+
}
59+
60+
return dest[:sz], nil
61+
}
62+
63+
// dogetxattr is a wrapper that retries on EINTR
64+
func dogetxattr(path, attr string, dest []byte) (int, error) {
65+
for {
66+
sz, err := unix.Getxattr(path, attr, dest)
67+
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
68+
return sz, err
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)