Skip to content

Commit

Permalink
Unconditionally quote all input to avoid ANSI injection
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardobranco777 committed Jan 21, 2024
1 parent 82a360f commit e979cd6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ $(BIN): *.go
.PHONY: test
test:
@go vet
@golint
@staticcheck

.PHONY: clean
clean:
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ Excerpt from `zypper` manual:
```
Usage of ./restartable:
-P, --proc string proc directory (default "/proc")
-Q, --quote quote filenames
-s, --short count Create a short table not showing the deleted files. Given twice, show only processes which are associated with a system service. Given three times, list the associated system service names only.
-u, --user show user services instead of system services
-v, --verbose verbose output
Expand Down
23 changes: 12 additions & 11 deletions restartable.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package main

import (
"bytes"
"fmt"
"golang.org/x/sys/unix"
"log"
Expand Down Expand Up @@ -33,7 +34,6 @@ var usernames map[int]string

var opts struct {
proc string
quote bool
short int
user bool
verbose bool
Expand All @@ -51,11 +51,9 @@ var (
regexUserService = regexp.MustCompile(`\d+:[^:]*:/user\.slice/(?:.*/)?(.*)\.service$`)
)

// Quote special characters
func quoteString(str string) string {
if opts.quote {
return strconv.Quote(str)
}
return str
return strings.Trim(strconv.Quote(str), `"`);
}

func readFile(dirFd int, path string) ([]byte, error) {
Expand Down Expand Up @@ -85,7 +83,7 @@ func readLink(dirFd int, path string) (string, error) {
if n, err := unix.Readlinkat(dirFd, path, data); err != nil {
return "", err
} else if n != size {
return quoteString(string(data[:n])), err
return string(data[:n]), err
}
}
}
Expand Down Expand Up @@ -165,8 +163,12 @@ func getInfo(pidInt int) (info *proc, err error) {
if err != nil {
return nil, err
}
cmdline := strings.Split(string(data), "\x00")
cmdline = cmdline[:len(cmdline)-1]

cmdline := []string{}
if bytes.HasSuffix(data, []byte("\x00")) {
cmdline = strings.Split(quoteString(string(data)), "\x00")
cmdline = cmdline[:len(cmdline)-1]
}

command := ""
if opts.verbose {
Expand All @@ -177,15 +179,15 @@ func getInfo(pidInt int) (info *proc, err error) {
if err != nil {
exe = ""
}
exe = strings.TrimSuffix(exe, " (deleted)")
exe = strings.TrimSuffix(quoteString(exe), " (deleted)")

if len(cmdline) > 0 && !strings.HasPrefix(cmdline[0], "/") && exe != "" && filepath.Base(cmdline[0]) == filepath.Base(exe) {
command = exe + " " + strings.Join(cmdline[1:], " ")
} else {
command = strings.Join(cmdline, " ")
}
} else {
command = regexName.FindStringSubmatch(status)[1]
command = quoteString(regexName.FindStringSubmatch(status)[1])
// The command may be truncated to 15 chars in /proc/<pid>/status
// Also, kernel usermode helpers use "none"
if len(cmdline) > 0 && cmdline[0] != "" && (len(command) == 15 || command == "none") {
Expand Down Expand Up @@ -302,7 +304,6 @@ func init() {
log.SetFlags(0)

flag.StringVarP(&opts.proc, "proc", "P", "/proc", "proc directory")
flag.BoolVarP(&opts.quote, "quote", "Q", false, "quote filenames")
flag.CountVarP(&opts.short, "short", "s", "Create a short table not showing the deleted files. Given twice, show only processes which are associated with a system service. Given three times, list the associated system service names only.")
flag.BoolVarP(&opts.user, "user", "u", false, "show user services instead of system services")
flag.BoolVarP(&opts.verbose, "verbose", "v", false, "verbose output")
Expand Down

0 comments on commit e979cd6

Please sign in to comment.