diff --git a/shared/api/event.go b/shared/api/event.go index 7d6ea171fe..98f6c4b9c6 100644 --- a/shared/api/event.go +++ b/shared/api/event.go @@ -63,6 +63,7 @@ func (event *Event) ToLogging() (EventLogRecord, error) { Msg: e.Message, Ctx: ctx, } + return record, nil } else if event.Type == EventTypeLifecycle { e := &EventLifecycle{} @@ -114,6 +115,7 @@ func (event *Event) ToLogging() (EventLogRecord, error) { "Location", e.Location, }, } + return record, nil } diff --git a/shared/api/network_acl.go b/shared/api/network_acl.go index 0723328e8f..6fd6c47aa1 100644 --- a/shared/api/network_acl.go +++ b/shared/api/network_acl.go @@ -64,6 +64,7 @@ func (r *NetworkACLRule) Normalise() { for i, s := range subjects { subjects[i] = strings.TrimSpace(s) } + r.Source = strings.Join(subjects, ",") // Remove space from Destination subject list. @@ -71,6 +72,7 @@ func (r *NetworkACLRule) Normalise() { for i, s := range subjects { subjects[i] = strings.TrimSpace(s) } + r.Destination = strings.Join(subjects, ",") // Remove space from SourcePort port list. @@ -78,6 +80,7 @@ func (r *NetworkACLRule) Normalise() { for i, s := range ports { ports[i] = strings.TrimSpace(s) } + r.SourcePort = strings.Join(ports, ",") // Remove space from DestinationPort port list. @@ -85,6 +88,7 @@ func (r *NetworkACLRule) Normalise() { for i, s := range ports { ports[i] = strings.TrimSpace(s) } + r.DestinationPort = strings.Join(ports, ",") } diff --git a/shared/api/network_forward.go b/shared/api/network_forward.go index 38a83f8e07..3ecca813ea 100644 --- a/shared/api/network_forward.go +++ b/shared/api/network_forward.go @@ -48,6 +48,7 @@ func (p *NetworkForwardPort) Normalise() { for i, s := range subjects { subjects[i] = strings.TrimSpace(s) } + p.ListenPort = strings.Join(subjects, ",") // Remove space from TargetPort list. @@ -55,6 +56,7 @@ func (p *NetworkForwardPort) Normalise() { for i, s := range subjects { subjects[i] = strings.TrimSpace(s) } + p.TargetPort = strings.Join(subjects, ",") } diff --git a/shared/archive.go b/shared/archive.go index cd22ceb5a1..d9090d6fc6 100644 --- a/shared/archive.go +++ b/shared/archive.go @@ -13,6 +13,7 @@ func DetectCompression(fname string) ([]string, string, []string, error) { if err != nil { return nil, "", nil, err } + defer func() { _ = f.Close() }() return DetectCompressionFile(f) diff --git a/shared/cancel/http.go b/shared/cancel/http.go index 4c3f0aabde..c682d856c9 100644 --- a/shared/cancel/http.go +++ b/shared/cancel/http.go @@ -44,6 +44,7 @@ func (c *HTTPRequestCanceller) Cancel() error { cancel() delete(c.reqCancel, req) } + c.lock.Unlock() return nil diff --git a/shared/cert.go b/shared/cert.go index 241c41de31..d896a2fa3f 100644 --- a/shared/cert.go +++ b/shared/cert.go @@ -91,6 +91,7 @@ func KeyPairAndCA(dir, prefix string, kind CertKind, addHosts bool) (*CertInfo, ca: ca, crl: crl, } + return info, nil } @@ -156,6 +157,7 @@ func (c *CertInfo) Fingerprint() string { if err != nil { panic("invalid public key material") } + return fingerprint } @@ -184,9 +186,11 @@ func TestingKeyPair() *CertInfo { if err != nil { panic(fmt.Sprintf("invalid X509 keypair material: %v", err)) } + cert := &CertInfo{ keypair: keypair, } + return cert } @@ -198,9 +202,11 @@ func TestingAltKeyPair() *CertInfo { if err != nil { panic(fmt.Sprintf("invalid X509 keypair material: %v", err)) } + cert := &CertInfo{ keypair: keypair, } + return cert } diff --git a/shared/cert_test.go b/shared/cert_test.go index 1962153935..f9c0800dd8 100644 --- a/shared/cert_test.go +++ b/shared/cert_test.go @@ -18,36 +18,45 @@ func TestKeyPairAndCA(t *testing.T) { if err != nil { t.Errorf("failed to create temporary dir: %v", err) } + defer func() { _ = os.RemoveAll(dir) }() info, err := shared.KeyPairAndCA(dir, "test", shared.CertServer, true) if err != nil { t.Errorf("initial call to KeyPairAndCA failed: %v", err) } + if info.CA() != nil { t.Errorf("expected CA certificate to be nil") } + if len(info.KeyPair().Certificate) == 0 { t.Errorf("expected key pair to be non-empty") } + if !shared.PathExists(filepath.Join(dir, "test.crt")) { t.Errorf("no public key file was saved") } + if !shared.PathExists(filepath.Join(dir, "test.key")) { t.Errorf("no secret key file was saved") } + cert, err := x509.ParseCertificate(info.KeyPair().Certificate[0]) if err != nil { t.Errorf("failed to parse generated public x509 key cert: %v", err) } + if cert.ExtKeyUsage[0] != x509.ExtKeyUsageServerAuth { t.Errorf("expected to find server auth key usage extension") } + block, _ := pem.Decode(info.PublicKey()) if block == nil { t.Errorf("expected PublicKey to be decodable") return } + _, err = x509.ParseCertificate(block.Bytes) if err != nil { t.Errorf("failed to parse encoded public x509 key cert: %v", err) @@ -58,30 +67,37 @@ func TestGenerateMemCert(t *testing.T) { if testing.Short() { t.Skip("skipping cert generation in short mode") } + cert, key, err := shared.GenerateMemCert(false, true) if err != nil { t.Error(err) return } + if cert == nil { t.Error("GenerateMemCert returned a nil cert") return } + if key == nil { t.Error("GenerateMemCert returned a nil key") return } + block, rest := pem.Decode(cert) if len(rest) != 0 { t.Errorf("GenerateMemCert returned a cert with trailing content: %q", string(rest)) } + if block.Type != "CERTIFICATE" { t.Errorf("GenerateMemCert returned a cert with Type %q not \"CERTIFICATE\"", block.Type) } + block, rest = pem.Decode(key) if len(rest) != 0 { t.Errorf("GenerateMemCert returned a key with trailing content: %q", string(rest)) } + if block.Type != "EC PRIVATE KEY" { t.Errorf("GenerateMemCert returned a cert with Type %q not \"EC PRIVATE KEY\"", block.Type) } diff --git a/shared/dnsutil/dnsutil.go b/shared/dnsutil/dnsutil.go index 08f868eb82..7c2b3d482e 100644 --- a/shared/dnsutil/dnsutil.go +++ b/shared/dnsutil/dnsutil.go @@ -38,9 +38,11 @@ func IsReverse(name string) int { if strings.HasSuffix(name, IP4arpa) { return 1 } + if strings.HasSuffix(name, IP6arpa) { return 2 } + return 0 } @@ -49,10 +51,12 @@ func reverse(slice []string) string { j := len(slice) - i - 1 slice[i], slice[j] = slice[j], slice[i] } + ip := net.ParseIP(strings.Join(slice, ".")).To4() if ip == nil { return "" } + return ip.String() } @@ -64,14 +68,17 @@ func reverse6(slice []string) string { j := len(slice) - i - 1 slice[i], slice[j] = slice[j], slice[i] } + slice6 := []string{} for i := 0; i < len(slice)/4; i++ { slice6 = append(slice6, strings.Join(slice[i*4:i*4+4], "")) } + ip := net.ParseIP(strings.Join(slice6, ":")).To16() if ip == nil { return "" } + return ip.String() } diff --git a/shared/idmap/idmapset_linux.go b/shared/idmap/idmapset_linux.go index 83027b5c0c..27ffe86e7c 100644 --- a/shared/idmap/idmapset_linux.go +++ b/shared/idmap/idmapset_linux.go @@ -216,18 +216,21 @@ func (e *IdmapEntry) parse(s string) error { if err != nil { return err } + e.Nsid = int64(nsid) hostid, err := strconv.ParseUint(split[2], 10, 32) if err != nil { return err } + e.Hostid = int64(hostid) maprange, err := strconv.ParseUint(split[3], 10, 32) if err != nil { return err } + e.Maprange = int64(maprange) // wraparound @@ -288,6 +291,7 @@ func Extend(slice []IdmapEntry, element IdmapEntry) []IdmapEntry { copy(newSlice, slice) slice = newSlice } + slice = slice[0 : n+1] slice[n] = element return slice @@ -379,6 +383,7 @@ func (m IdmapSet) ValidRanges() ([]*IdRange, error) { if err != nil { return nil, err } + sort.Sort(idmap) for _, mapEntry := range idmap.Idmap { @@ -449,6 +454,7 @@ func (m *IdmapSet) AddSafe(i IdmapEntry) error { if lower.Maprange > 0 { result = append(result, lower) } + result = append(result, i) if upper.Maprange > 0 { result = append(result, upper) @@ -472,6 +478,7 @@ func (m IdmapSet) ToLxcString() []string { } } } + return lines } @@ -517,9 +524,11 @@ func (m IdmapSet) Append(s string) (IdmapSet, error) { if err != nil { return m, err } + if m.Intersects(e) { return m, fmt.Errorf("Conflicting id mapping") } + m.Idmap = Extend(m.Idmap, e) return m, nil } @@ -584,6 +593,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, testmode bool, how stri if err != nil { return fmt.Errorf("Expand symlinks: %w", err) } + dir = filepath.Join(tmp, filepath.Base(dir)) dir = strings.TrimRight(dir, "/") @@ -706,6 +716,7 @@ func getFromShadow(fname string, username string) ([][]int64, error) { if err != nil { return nil, err } + defer func() { _ = f.Close() }() scanner := bufio.NewScanner(f) @@ -756,6 +767,7 @@ func getFromProc(fname string) ([][]int64, error) { if err != nil { return nil, err } + defer func() { _ = f.Close() }() scanner := bufio.NewScanner(f) @@ -1082,5 +1094,6 @@ func GetIdmapSet() *IdmapSet { } } } + return idmapSet } diff --git a/shared/idmap/parse_linux.go b/shared/idmap/parse_linux.go index 9cdfd3baac..d8900f9a04 100644 --- a/shared/idmap/parse_linux.go +++ b/shared/idmap/parse_linux.go @@ -75,18 +75,21 @@ func ParseRawIdmap(value string) ([]IdmapEntry, error) { if err != nil { return nil, err } + case "uid": entry.Isuid = true err := ret.AddSafe(entry) if err != nil { return nil, err } + case "gid": entry.Isgid = true err := ret.AddSafe(entry) if err != nil { return nil, err } + default: return nil, fmt.Errorf("Invalid ID map type %q", line) } diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go index e1c24e7017..e26830608c 100644 --- a/shared/idmap/shift_linux.go +++ b/shared/idmap/shift_linux.go @@ -409,6 +409,7 @@ func shiftAclType(path string, aclType int, shiftIds func(uid int64, gid int64) if acl == nil { return nil } + defer C.acl_free(unsafe.Pointer(acl)) // Iterate through all ACL entries @@ -475,6 +476,7 @@ func SupportsVFS3Fscaps(prefix string) bool { if err != nil { return false } + defer func() { _ = tmpfile.Close() }() defer func() { _ = os.Remove(tmpfile.Name()) }() @@ -528,6 +530,7 @@ func UnshiftACL(value string, set *IdmapSet) (string, error) { if count < 0 { return "", fmt.Errorf("Invalid ACL count") } + if count == 0 { return "", fmt.Errorf("No valid ACLs found") } @@ -544,6 +547,7 @@ func UnshiftACL(value string, set *IdmapSet) (string, error) { entry.e_id = C.native_to_le32(C.int(uid)) logger.Debugf("Unshifting ACL_USER from uid %d to uid %d", ouid, uid) } + case C.ACL_GROUP: ogid := int64(C.le32_to_native(entry.e_id)) _, gid := set.ShiftFromNs(-1, ogid) @@ -551,6 +555,7 @@ func UnshiftACL(value string, set *IdmapSet) (string, error) { entry.e_id = C.native_to_le32(C.int(gid)) logger.Debugf("Unshifting ACL_GROUP from gid %d to gid %d", ogid, gid) } + case C.ACL_USER_OBJ: logger.Debugf("Ignoring ACL type ACL_USER_OBJ") case C.ACL_GROUP_OBJ: diff --git a/shared/instancewriter/instance_tar_writer.go b/shared/instancewriter/instance_tar_writer.go index 31ab0b46a1..1b172935bf 100644 --- a/shared/instancewriter/instance_tar_writer.go +++ b/shared/instancewriter/instance_tar_writer.go @@ -115,6 +115,7 @@ func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi os.FileI logger.Debugf("Failed to unshift ACL access permissions of %q: %v", srcPath, err) continue } + hdr.PAXRecords["SCHILY.acl.access"] = aclAccess } else if key == "system.posix_acl_default" && ctw.idmapSet != nil { aclDefault, err := idmap.UnshiftACL(val, ctw.idmapSet) @@ -122,6 +123,7 @@ func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi os.FileI logger.Debugf("Failed to unshift ACL default permissions of %q: %v", srcPath, err) continue } + hdr.PAXRecords["SCHILY.acl.default"] = aclDefault } else if key == "security.capability" && ctw.idmapSet != nil { vfsCaps, err := idmap.UnshiftCaps(val, ctw.idmapSet) @@ -129,6 +131,7 @@ func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi os.FileI logger.Debugf("Failed to unshift VFS capabilities of %q: %v", srcPath, err) continue } + hdr.PAXRecords["SCHILY.xattr."+key] = vfsCaps } else { hdr.PAXRecords["SCHILY.xattr."+key] = val @@ -146,6 +149,7 @@ func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi os.FileI if err != nil { return fmt.Errorf("Failed to open file %q: %w", srcPath, err) } + defer func() { _ = f.Close() }() r := io.Reader(f) @@ -190,5 +194,6 @@ func (ctw *InstanceTarWriter) Close() error { if err != nil { return fmt.Errorf("Failed to close tar writer: %w", err) } + return nil } diff --git a/shared/netutils/network_linux.go b/shared/netutils/network_linux.go index 80a1fe8c36..efeadb8caf 100644 --- a/shared/netutils/network_linux.go +++ b/shared/netutils/network_linux.go @@ -29,6 +29,7 @@ func WebsocketExecMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadCloser if err != nil { logger.Debugf("Got err writing barrier %s", err) } + readDone <- true return } diff --git a/shared/netutils/network_linux_cgo.go b/shared/netutils/network_linux_cgo.go index 17e5b7a4b3..f435a3c37b 100644 --- a/shared/netutils/network_linux_cgo.go +++ b/shared/netutils/network_linux_cgo.go @@ -72,6 +72,7 @@ func NetnsGetifaddrs(initPID int32) (map[string]api.InstanceStateNetwork, error) if err != nil { return nil, err } + defer func() { _ = f.Close() }() netnsID = C.netns_get_nsid(C.__s32(f.Fd())) @@ -86,6 +87,7 @@ func NetnsGetifaddrs(initPID int32) (map[string]api.InstanceStateNetwork, error) if ret < 0 { return nil, fmt.Errorf("Failed to retrieve network interfaces and addresses") } + defer C.netns_freeifaddrs(ifaddrs) if netnsID >= 0 && !netnsidAware { @@ -125,6 +127,7 @@ func NetnsGetifaddrs(initPID int32) (map[string]api.InstanceStateNetwork, error) if (addr.ifa_flags & C.IFF_UP) > 0 { netState = "up" } + addNetwork.State = netState addNetwork.Type = netType addNetwork.Mtu = int(addr.ifa_mtu) @@ -205,6 +208,7 @@ func NetnsGetifaddrs(initPID int32) (map[string]api.InstanceStateNetwork, error) addNetwork.Counters.PacketsDroppedInbound = int64(addr.ifa_stats64.rx_dropped) addNetwork.Counters.PacketsDroppedOutbound = int64(addr.ifa_stats64.tx_dropped) } + ifName := C.GoString(addr.ifa_name) networks[ifName] = addNetwork diff --git a/shared/network.go b/shared/network.go index 191300a5ff..d14a2a5b13 100644 --- a/shared/network.go +++ b/shared/network.go @@ -244,6 +244,7 @@ func WebsocketRecvStream(w io.Writer, conn *websocket.Conn) chan bool { logger.Debug("WebsocketRecvStream didn't write all of buf") break } + if err != nil { logger.Debug("WebsocketRecvStream error writing buf", logger.Ctx{"err": err}) break @@ -354,11 +355,13 @@ func DefaultWriter(conn *websocket.Conn, w io.WriteCloser, writeDone chan<- bool logger.Debug("DefaultWriter got error writing to writer", logger.Ctx{"err": err}) break } + i, err := w.Write(buf) if i != len(buf) { logger.Debug("DefaultWriter didn't write all of buf") break } + if err != nil { logger.Debug("DefaultWriter error writing buf", logger.Ctx{"err": err}) break diff --git a/shared/network_ip.go b/shared/network_ip.go index 49cf3b6a6a..bb3dc03390 100644 --- a/shared/network_ip.go +++ b/shared/network_ip.go @@ -19,6 +19,7 @@ func (r *IPRange) ContainsIP(ip net.IP) bool { // the range is only a single IP return r.Start.Equal(ip) } + return bytes.Compare(ip, r.Start) >= 0 && bytes.Compare(ip, r.End) <= 0 } @@ -26,5 +27,6 @@ func (r *IPRange) String() string { if r.End == nil { return r.Start.String() } + return fmt.Sprintf("%v-%v", r.Start, r.End) } diff --git a/shared/network_windows.go b/shared/network_windows.go index 09aa8b4ea9..39c2b8452f 100644 --- a/shared/network_windows.go +++ b/shared/network_windows.go @@ -19,6 +19,7 @@ func systemCertPool() (*x509.CertPool, error) { if systemRoots == nil { return nil, fmt.Errorf("Bad system root pool") } + return systemRoots, nil } @@ -30,6 +31,7 @@ func initSystemRoots() { systemRoots = nil return } + defer windows.CertCloseStore(store, 0) roots := x509.NewCertPool() @@ -45,6 +47,7 @@ func initSystemRoots() { systemRoots = nil return } + if cert == nil { break } diff --git a/shared/osarch/architectures.go b/shared/osarch/architectures.go index de0909ecc0..8c3850eb76 100644 --- a/shared/osarch/architectures.go +++ b/shared/osarch/architectures.go @@ -132,10 +132,12 @@ func ArchitectureGetLocalID() (int, error) { if err != nil { return -1, err } + id, err := ArchitectureId(name) if err != nil { return -1, err } + return id, nil } @@ -145,5 +147,6 @@ func SupportedArchitectures() []string { for _, archName := range architectureNames { result = append(result, archName) } + return result } diff --git a/shared/osarch/tempfile_test.go b/shared/osarch/tempfile_test.go index 77cef8ea0d..75c66dfe36 100644 --- a/shared/osarch/tempfile_test.go +++ b/shared/osarch/tempfile_test.go @@ -13,11 +13,13 @@ func WriteTempFile(s *suite.Suite, dir string, prefix string, content string) (s if err != nil { s.T().Errorf("Failed to create temporary file: %v", err) } + defer func() { _ = f.Close() }() _, err = f.WriteString(content) if err != nil { s.T().Errorf("Failed to write string to temp file: %v", err) } + return f.Name(), func() { _ = os.Remove(f.Name()) } } diff --git a/shared/proxy.go b/shared/proxy.go index 8c3705b546..aaf9cc7031 100644 --- a/shared/proxy.go +++ b/shared/proxy.go @@ -14,9 +14,11 @@ var ( httpProxyEnv = &envOnce{ names: []string{"HTTP_PROXY", "http_proxy"}, } + httpsProxyEnv = &envOnce{ names: []string{"HTTPS_PROXY", "https_proxy"}, } + noProxyEnv = &envOnce{ names: []string{"NO_PROXY", "no_proxy"}, } @@ -60,12 +62,14 @@ func ProxyFromConfig(httpsProxy string, httpProxy string, noProxy string) func(r if proxy == "" { proxy = httpsProxyEnv.Get() } + port = ":443" case "http": proxy = httpProxy if proxy == "" { proxy = httpProxyEnv.Get() } + port = ":80" default: return nil, fmt.Errorf("unknown scheme %s", req.URL.Scheme) @@ -84,6 +88,7 @@ func ProxyFromConfig(httpsProxy string, httpProxy string, noProxy string) func(r if err != nil { return nil, err } + if !use { return nil, nil } @@ -100,6 +105,7 @@ func ProxyFromConfig(httpsProxy string, httpProxy string, noProxy string) func(r if err != nil { return nil, fmt.Errorf("invalid proxy address %q: %w", proxy, err) } + return proxyURL, nil } } @@ -116,13 +122,16 @@ func useProxy(addr string, noProxy string) (bool, error) { if len(addr) == 0 { return true, nil } + host, _, err := net.SplitHostPort(addr) if err != nil { return false, nil } + if host == "localhost" { return false, nil } + ip := net.ParseIP(host) if ip != nil { if ip.IsLoopback() { @@ -144,12 +153,15 @@ func useProxy(addr string, noProxy string) (bool, error) { if len(p) == 0 { continue } + if hasPort(p) { p = p[:strings.LastIndex(p, ":")] } + if addr == p { return false, nil } + if _, pnet, err := net.ParseCIDR(p); err == nil && ip != nil { // IPv4/CIDR, IPv6/CIDR if pnet.Contains(ip) { @@ -160,6 +172,7 @@ func useProxy(addr string, noProxy string) (bool, error) { // noProxy ".foo.com" matches "bar.foo.com" or "foo.com" return false, nil } + if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' { // noProxy "foo.com" matches "bar.foo.com" return false, nil diff --git a/shared/simplestreams/products.go b/shared/simplestreams/products.go index 1e64b3aa43..de71debf4d 100644 --- a/shared/simplestreams/products.go +++ b/shared/simplestreams/products.go @@ -149,6 +149,7 @@ func (s *Products) ToLXD() ([]api.Image, map[string][][]string) { if version.Label != "" { description = fmt.Sprintf("%s (%s)", description, version.Label) } + description = fmt.Sprintf("%s (%s)", description, name) image := api.Image{} diff --git a/shared/simplestreams/simplestreams.go b/shared/simplestreams/simplestreams.go index 41a18e0064..5e2404ac14 100644 --- a/shared/simplestreams/simplestreams.go +++ b/shared/simplestreams/simplestreams.go @@ -121,6 +121,7 @@ func (s *SimpleStreams) cachedDownload(path string) ([]byte, error) { return nil, err } + defer func() { _ = r.Body.Close() }() if r.StatusCode != http.StatusOK { diff --git a/shared/subprocess/bgpm_test.go b/shared/subprocess/bgpm_test.go index 5e8f77dc03..0680b5d7bc 100644 --- a/shared/subprocess/bgpm_test.go +++ b/shared/subprocess/bgpm_test.go @@ -49,6 +49,7 @@ func TestSignalHandling(t *testing.T) { if err != nil { t.Error("Could not open file ", err) } + defer func() { _ = file.Close() }() var text = make([]byte, 1024) @@ -159,6 +160,7 @@ func TestProcessStartWaitExit(t *testing.T) { if err != nil { t.Error("Could not open file: ", err) } + defer func() { _ = file.Close() }() exp = "hello again\nwaiting now\n" diff --git a/shared/subprocess/manager.go b/shared/subprocess/manager.go index 0dff8e491c..b67588352d 100644 --- a/shared/subprocess/manager.go +++ b/shared/subprocess/manager.go @@ -36,6 +36,7 @@ func NewProcess(name string, args []string, stdoutPath string, stderrPath string if err != nil { return nil, fmt.Errorf("Error when creating process object: %w", err) } + p.closeFds = true return p, nil diff --git a/shared/subprocess/proc.go b/shared/subprocess/proc.go index bd99c61583..efa9736796 100644 --- a/shared/subprocess/proc.go +++ b/shared/subprocess/proc.go @@ -123,6 +123,7 @@ func (p *Process) start(fds []*os.File) error { } else { cmd = exec.Command(p.Name, p.Args...) } + cmd.Stdout = p.Stdout cmd.Stderr = p.Stderr cmd.Stdin = p.Stdin @@ -130,6 +131,7 @@ func (p *Process) start(fds []*os.File) error { if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } + cmd.SysProcAttr.Setsid = true if p.UID != 0 || p.GID != 0 { @@ -210,6 +212,7 @@ func (p *Process) Reload() error { if err != nil { return fmt.Errorf("Could not reload process: %w", err) } + return nil } else if strings.Contains(err.Error(), "process already finished") { return ErrNotRunning @@ -242,6 +245,7 @@ func (p *Process) Signal(signal int64) error { if err != nil { return fmt.Errorf("Could not signal process: %w", err) } + return nil } else if strings.Contains(err.Error(), "process already finished") { return ErrNotRunning diff --git a/shared/usbid/load.go b/shared/usbid/load.go index eb54bfbd88..335a542d6e 100644 --- a/shared/usbid/load.go +++ b/shared/usbid/load.go @@ -35,8 +35,10 @@ func Load() { if !os.IsNotExist(err) { log.Printf("usbid: failed to load: %s", err) } + return } + defer func() { _ = usbids.Close() }() ids, cls, err := ParseIDs(usbids) diff --git a/shared/usbid/parse.go b/shared/usbid/parse.go index 4598c3ca35..46426be79a 100644 --- a/shared/usbid/parse.go +++ b/shared/usbid/parse.go @@ -104,6 +104,7 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { err = fmt.Errorf("malformatted id %q: %w", pieces[0], err) return } + id = i return @@ -121,6 +122,7 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { vendor = &Vendor{ Name: name, } + vendors[id] = vendor case 1: @@ -131,9 +133,11 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { device = &Product{ Name: name, } + if vendor.Product == nil { vendor.Product = make(map[ID]*Product) } + vendor.Product[id] = device case 2: @@ -144,6 +148,7 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { if device.Interface == nil { device.Interface = make(map[ID]string) } + device.Interface[id] = name default: @@ -163,6 +168,7 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { class = &Class{ Name: name, } + classes[ClassCode(id)] = class case 1: @@ -173,9 +179,11 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { subclass = &SubClass{ Name: name, } + if class.SubClass == nil { class.SubClass = make(map[ClassCode]*SubClass) } + class.SubClass[ClassCode(id)] = subclass case 2: @@ -186,6 +194,7 @@ func ParseIDs(r io.Reader) (map[ID]*Vendor, map[ClassCode]*Class, error) { if subclass.Protocol == nil { subclass.Protocol = make(map[Protocol]string) } + subclass.Protocol[Protocol(id)] = name default: @@ -213,6 +222,7 @@ parseLines: case isPrefix: return nil, nil, fmt.Errorf("line %d: line too long", lineno) } + line := string(b) if len(line) == 0 || line[0] == '#' { @@ -223,6 +233,7 @@ parseLines: if err != nil { return nil, nil, fmt.Errorf("line %d: %w", lineno, err) } + if k != "" { kind = k } @@ -233,6 +244,7 @@ parseLines: case "C": err = parseClass(level, id, name) } + if err != nil { return nil, nil, fmt.Errorf("line %d: %w", lineno, err) } diff --git a/shared/usbid/types.go b/shared/usbid/types.go index a372e720f2..79a7561132 100644 --- a/shared/usbid/types.go +++ b/shared/usbid/types.go @@ -87,6 +87,7 @@ func (c ClassCode) String() string { if d, ok := classDescription[c]; ok { return d } + return strconv.Itoa(int(c)) } diff --git a/shared/util.go b/shared/util.go index b17e8a7548..4bd3adcfdc 100644 --- a/shared/util.go +++ b/shared/util.go @@ -48,6 +48,7 @@ func URLEncode(path string, query map[string]string) (string, error) { for key, value := range query { params.Add(key, value) } + u.RawQuery = params.Encode() return u.String(), nil } @@ -68,6 +69,7 @@ func PathExists(name string) bool { if err != nil && os.IsNotExist(err) { return false } + return true } @@ -77,6 +79,7 @@ func PathIsEmpty(path string) (bool, error) { if err != nil { return false, err } + defer func() { _ = f.Close() }() // read in ONLY one file @@ -86,6 +89,7 @@ func PathIsEmpty(path string) (bool, error) { if err == io.EOF { return true, nil } + return false, err } @@ -95,6 +99,7 @@ func IsDir(name string) bool { if err != nil { return false } + return stat.IsDir() } @@ -105,6 +110,7 @@ func IsUnixSocket(path string) bool { if err != nil { return false } + return (stat.Mode() & os.ModeSocket) == os.ModeSocket } @@ -149,6 +155,7 @@ func HostPathFollow(path string) string { if err != nil { return path } + target = strings.TrimSpace(target) if path == HostPath(target) { @@ -225,6 +232,7 @@ func CachePath(path ...string) string { if varDir != "" { logDir = filepath.Join(varDir, "cache") } + items := []string{logDir} items = append(items, path...) return filepath.Join(items...) @@ -238,6 +246,7 @@ func LogPath(path ...string) string { if varDir != "" { logDir = filepath.Join(varDir, "logs") } + items := []string{logDir} items = append(items, path...) return filepath.Join(items...) @@ -344,6 +353,7 @@ func ReadStdin() ([]byte, error) { if err != nil { return nil, err } + return line, nil } @@ -448,6 +458,7 @@ func FileCopy(source string, dest string) error { if err != nil { return err } + defer func() { _ = s.Close() }() d, err := os.Create(dest) @@ -557,6 +568,7 @@ func MkdirAllOwner(path string, perm os.FileMode, uid int, gid int) error { if dir.IsDir() { return nil } + return fmt.Errorf("path exists but isn't a directory") } @@ -594,8 +606,10 @@ func MkdirAllOwner(path string, perm os.FileMode, uid int, gid int) error { if err1 == nil && dir.IsDir() { return nil } + return err } + return nil } @@ -744,6 +758,7 @@ func RunningInUserNS() bool { if err != nil { return false } + defer func() { _ = file.Close() }() buf := bufio.NewReader(file) @@ -758,6 +773,7 @@ func RunningInUserNS() bool { if a == 0 && b == 0 && c == 4294967295 { return false } + return true } @@ -791,6 +807,7 @@ func TextEditor(inPath string, inContent []byte) ([]byte, error) { if err != nil { return []byte{}, err } + revert := revert.New() defer revert.Fail() revert.Add(func() { @@ -855,6 +872,7 @@ func ParseMetadata(metadata any) (map[string]any, error) { if k.Kind() != reflect.String { return nil, fmt.Errorf("Invalid metadata provided (key isn't a string)") } + newMetadata[k.String()] = s.MapIndex(k).Interface() } } else if s.Kind() == reflect.Ptr && !s.Elem().IsValid() { @@ -875,6 +893,7 @@ func RemoveDuplicatesFromString(s string, sep string) string { for s = strings.Replace(s, dup, sep, -1); strings.Contains(s, dup); s = strings.Replace(s, dup, sep, -1) { } + return s } @@ -917,6 +936,7 @@ func RunCommandSplit(env []string, filesInherit []*os.File, name string, arg ... Stderr: stderr.String(), Err: err, } + return stdout.String(), stderr.String(), err } @@ -1055,6 +1075,7 @@ func DownloadFileHash(ctx context.Context, httpClient *http.Client, useragent st } else { req, err = http.NewRequest("GET", url, nil) } + if err != nil { return -1, err } @@ -1068,6 +1089,7 @@ func DownloadFileHash(ctx context.Context, httpClient *http.Client, useragent st if err != nil { return -1, err } + defer func() { _ = r.Body.Close() }() defer close(doneCh) @@ -1120,6 +1142,7 @@ func ParseNumberFromFile(file string) (int64, error) { if err != nil { return int64(0), err } + defer func() { _ = f.Close() }() buf := make([]byte, 4096) @@ -1242,6 +1265,7 @@ func JoinUrls(baseUrl, p string) (string, error) { if err != nil { return "", err } + u.Path = path.Join(u.Path, p) return u.String(), nil } diff --git a/shared/util_linux.go b/shared/util_linux.go index 690a2f0154..2cd7fd15ec 100644 --- a/shared/util_linux.go +++ b/shared/util_linux.go @@ -30,6 +30,7 @@ func GetFileStat(p string) (uid int, gid int, major uint32, minor uint32, inode if err != nil { return } + uid = int(stat.Uid) gid = int(stat.Gid) inode = uint64(stat.Ino) @@ -61,6 +62,7 @@ func SetSize(fd int, width int, height int) (err error) { if _, _, err := unix.Syscall6(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TIOCSWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { return err } + return nil } @@ -74,17 +76,20 @@ func llistxattr(path string, list []byte) (sz int, err error) { if err != nil { return } + var _p1 unsafe.Pointer if len(list) > 0 { _p1 = unsafe.Pointer(&list[0]) } else { _p1 = unsafe.Pointer(nil) } + r0, _, e1 := unix.Syscall(unix.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(list))) sz = int(r0) if e1 != 0 { err = e1 } + return } @@ -101,8 +106,10 @@ func GetAllXattr(path string) (xattrs map[string]string, err error) { if err == unix.EOPNOTSUPP { return nil, nil } + return nil, err } + if pre == 0 { return nil, nil } @@ -113,6 +120,7 @@ func GetAllXattr(path string) (xattrs map[string]string, err error) { if err != nil || post < 0 { return nil, err } + if post > pre { return nil, fmt.Errorf("Extended attribute list size increased from %d to %d during retrieval", pre, post) } @@ -299,6 +307,7 @@ func GetMeminfo(field string) (int64, error) { if err != nil { return -1, err } + defer func() { _ = f.Close() }() // Read it line by line @@ -341,9 +350,11 @@ func OpenPtyInDevpts(devpts_fd int, uid, gid int64) (*os.File, *os.File, error) } else { fd, err = unix.Openat(-1, "/dev/ptmx", unix.O_RDWR|unix.O_CLOEXEC|unix.O_NOCTTY, 0) } + if err != nil { return nil, nil, err } + ptx = os.NewFile(uintptr(fd), "/dev/pts/ptmx") revert.Add(func() { _ = ptx.Close() }) @@ -629,6 +640,7 @@ func GetPollRevents(fd int, timeout int, flags int) (int, int, error) { Events: int16(flags), Revents: 0, } + pollFds := []unix.PollFd{pollFd} again: diff --git a/shared/util_linux_cgo.go b/shared/util_linux_cgo.go index efb62feb60..9e53a2413e 100644 --- a/shared/util_linux_cgo.go +++ b/shared/util_linux_cgo.go @@ -73,6 +73,7 @@ func unCloexec(fd int) error { if errno != 0 { err = errno } + return err } diff --git a/shared/util_linux_test.go b/shared/util_linux_test.go index f761328a9e..22b8fe11f1 100644 --- a/shared/util_linux_test.go +++ b/shared/util_linux_test.go @@ -22,6 +22,7 @@ func TestGetAllXattr(t *testing.T) { t.Error(err) return } + defer func() { _ = os.Remove(xattrFile.Name()) }() _ = xattrFile.Close() @@ -30,6 +31,7 @@ func TestGetAllXattr(t *testing.T) { t.Error(err) return } + defer func() { _ = os.Remove(xattrDir) }() for k, v := range testxattr { @@ -38,15 +40,18 @@ func TestGetAllXattr(t *testing.T) { t.Log(err) return } + if err != nil { t.Error(err) return } + err = unix.Setxattr(xattrDir, k, []byte(v), 0) if err == unix.ENOTSUP { t.Log(err) return } + if err != nil { t.Error(err) return diff --git a/shared/util_test.go b/shared/util_test.go index f8555a6e7f..cb344b07a4 100644 --- a/shared/util_test.go +++ b/shared/util_test.go @@ -47,6 +47,7 @@ func TestFileCopy(t *testing.T) { t.Error(err) return } + defer func() { _ = os.Remove(source.Name()) }() if err := WriteAll(source, helloWorld); err != nil { @@ -54,6 +55,7 @@ func TestFileCopy(t *testing.T) { t.Error(err) return } + _ = source.Close() dest, err := ioutil.TempFile("", "") @@ -62,6 +64,7 @@ func TestFileCopy(t *testing.T) { t.Error(err) return } + _ = dest.Close() if err := FileCopy(source.Name(), dest.Name()); err != nil { @@ -215,6 +218,7 @@ func TestRemoveElementsFromStringSlice(t *testing.T) { list []string expectedList []string } + tests := []test{ { elementsToRemove: []string{"one", "two", "three"}, diff --git a/shared/version/useragent.go b/shared/version/useragent.go index 01d08d7019..d37a6b1e9e 100644 --- a/shared/version/useragent.go +++ b/shared/version/useragent.go @@ -26,6 +26,7 @@ func getUserAgent() string { if err != nil { panic(err) } + osTokens := []string{cases.Title(language.English).String(arch)} osTokens = append(osTokens, getPlatformVersionStrings()...) diff --git a/shared/version/version.go b/shared/version/version.go index 941f8b7183..723f324d38 100644 --- a/shared/version/version.go +++ b/shared/version/version.go @@ -54,6 +54,7 @@ func Parse(s string) (*DottedVersion, error) { if len(matches) == 0 { return nil, fmt.Errorf("Can't parse a version") } + return NewDottedVersion(matches[1]) } @@ -63,6 +64,7 @@ func (v *DottedVersion) String() string { if v.Patch != -1 { version += fmt.Sprintf(".%d", v.Patch) } + return version } @@ -72,10 +74,12 @@ func (v *DottedVersion) Compare(other *DottedVersion) int { if result != 0 { return result } + result = compareInts(v.Minor, other.Minor) if result != 0 { return result } + return compareInts(v.Patch, other.Patch) }