Skip to content

Commit

Permalink
Replace github.com/s-urbaniak/uevent.go with github.com/pilebones/go-…
Browse files Browse the repository at this point in the history
…udev/netlink

github.com/s-urbaniak/uevent.go is unable to handle errors from udev
netlik listener. It just panics.

Issue #155
  • Loading branch information
anatol committed Jul 30, 2022
1 parent 27a7b5c commit a9475f7
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 53 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ require (
github.com/anatol/luks.go v0.0.0-20211210165108-5d9a15b4f614
github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef
github.com/cavaliergopher/cpio v1.0.1
github.com/google/go-tpm v0.3.3
github.com/google/renameio v1.0.1
github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd
github.com/jessevdk/go-flags v1.5.0
github.com/klauspost/compress v1.15.1
github.com/pilebones/go-udev v0.9.0
github.com/stretchr/testify v1.7.1
github.com/ulikunitz/xz v0.5.10
github.com/vishvananda/netlink v1.1.0
Expand Down
7 changes: 4 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0 h1:rnURfQKi7StDt+W
github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0/go.mod h1:mPog5NmM5znyLbUO9WQPJ4xQdVtuHPptPavY0055POc=
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca h1:60FgDd7iZj00Ggcm2VLkzRAuUSAMZrHqDcUqYApSG5A=
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca/go.mod h1:eehwvW8/vkT20kR75KYthbNZYCXyQVt4T6XGSLplJQ0=
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549 h1:CPuCjtWK5UI9KQPDhylGHfZe7Pp8j58WK7i3wpLemA0=
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549/go.mod h1:yO7hm0VhhOujsh+j0nn8ExPhAqIJh50MZOcKetKhAPA=
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef h1:YQzm9r8/ArTsQ6C3/h+w4Dz5dfkYkQbK/3ETLWW2i7Q=
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef/go.mod h1:JiDFhD1zjgMx9ONsHhhucGwMvCLrJMl/yu/l5qP4XFw=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
Expand Down Expand Up @@ -108,8 +106,9 @@ github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand Down Expand Up @@ -142,6 +141,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q=
github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
2 changes: 2 additions & 0 deletions init/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ func switchRoot() error {

// Cleanup the state before handing off the machine to the new init
func cleanup() {
close(udevQuitLoop)
udevConn.Close()
shutdownNetwork()
}

Expand Down
101 changes: 52 additions & 49 deletions init/udev.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"io"
"net"
"os"
"path/filepath"
Expand All @@ -11,14 +10,14 @@ import (
"strings"

"github.com/anatol/devmapper.go"
"github.com/anatol/uevent.go"
"github.com/pilebones/go-udev/netlink"
"golang.org/x/sys/unix"
)

// validDmEvent checks whether this udev event has correct flags.
// This is similar to checks done by /usr/lib/udev/rules.d/10-dm.rules udev rules.
func validDmEvent(ev *uevent.Uevent) bool {
dmCookie := ev.Vars["DM_COOKIE"]
func validDmEvent(ev netlink.UEvent) bool {
dmCookie := ev.Env["DM_COOKIE"]
if dmCookie == "" {
info("udev event does not contain DM_COOKIE")
return false
Expand Down Expand Up @@ -63,57 +62,61 @@ func validDmEvent(ev *uevent.Uevent) bool {
return true
}

var udevReader io.ReadCloser
var (
udevQuitLoop chan struct{}
udevConn *netlink.UEventConn
)

func udevListener() error {
defer func() {
// uevent.NewDecoder uses bufio.ReadString() that is blocking. If we try to close the underlying udev file descriptor
// while bufio tries to read from it then bufio panics. See issues #22, #31 and #153
// There is no clear way to prevent the panic so we just recover from it here and then safely exit the goroutine.
if r := recover(); r != nil {
warning("recovered udevListener panic: %v", r)
}
}()

var err error
udevReader, err = uevent.NewReader()
if err != nil {
return err
udevConn = new(netlink.UEventConn)
if err := udevConn.Connect(netlink.KernelEvent); err != nil {
return fmt.Errorf("unable to connect to Netlink Kobject UEvent socket")
}
defer udevReader.Close()
defer udevConn.Close()

dec := uevent.NewDecoder(udevReader)
queue := make(chan netlink.UEvent)
errors := make(chan error)
udevQuitLoop = udevConn.Monitor(queue, errors, nil)

exit:
for {
ev, err := dec.Decode()
if err == io.EOF {
// EOF is returned if uevent reader is closed concurrently
return nil
}
if err != nil {
return err
}
debug("udev event %+v", *ev)

// TODO: run each udev in a separate goroutine
if modalias, ok := ev.Vars["MODALIAS"]; ok {
go func() { check(loadModalias(modalias)) }()
} else if ev.Subsystem == "block" {
go func() { check(handleBlockDeviceUevent(ev)) }()
} else if ev.Subsystem == "net" {
go func() { check(handleNetworkUevent(ev)) }()
} else if ev.Subsystem == "hidraw" && ev.Action == "add" {
go func() { hidrawDevices <- ev.Vars["DEVNAME"] }()
select {
case ev, ok := <-queue:
if !ok {
break exit
}
handleUdevEvent(ev)
case err, ok := <-errors:
if !ok {
break exit
}
warning("udev: %+v", err)
}
}

return nil
}

func handleUdevEvent(ev netlink.UEvent) {
debug("udev event: %+v", ev)

if modalias, ok := ev.Env["MODALIAS"]; ok {
go func() { check(loadModalias(modalias)) }()
} else if ev.Env["SUBSYSTEM"] == "block" {
go func() { check(handleBlockDeviceUevent(ev)) }()
} else if ev.Env["SUBSYSTEM"] == "net" {
go func() { check(handleNetworkUevent(ev)) }()
} else if ev.Env["SUBSYSTEM"] == "hidraw" && ev.Action == "add" {
go func() { hidrawDevices <- ev.Env["DEVNAME"] }()
}
}

func handleNetworkUevent(ev *uevent.Uevent) error {
func handleNetworkUevent(ev netlink.UEvent) error {
if ev.Action != "add" {
return nil
}

ifname := ev.Vars["INTERFACE"]
ifname := ev.Env["INTERFACE"]
if ifname == "lo" {
return nil
}
Expand All @@ -140,8 +143,8 @@ func handleNetworkUevent(ev *uevent.Uevent) error {

var dmNameRe = regexp.MustCompile(`dm-\d+`)

func handleBlockDeviceUevent(ev *uevent.Uevent) error {
devName := ev.Vars["DEVNAME"]
func handleBlockDeviceUevent(ev netlink.UEvent) error {
devName := ev.Env["DEVNAME"]

if dmNameRe.MatchString(devName) {
// mapper devices should not be added on "add" uevent
Expand All @@ -159,10 +162,10 @@ func handleBlockDeviceUevent(ev *uevent.Uevent) error {

devPath := "/dev/" + devName

isPartition := ev.Vars["DEVTYPE"] == "partition"
isPartition := ev.Env["DEVTYPE"] == "partition"
if isPartition {
// if this device represents a partition inside a table (like GPT) then wait till the table is processed
parts := strings.Split(ev.Devpath, "/")
parts := strings.Split(ev.KObj, "/")
tablePath := "/dev/" + parts[len(parts)-2]
waitForDeviceToProcess(tablePath)
}
Expand All @@ -173,14 +176,14 @@ func handleBlockDeviceUevent(ev *uevent.Uevent) error {
// handleMapperDeviceUevent handles device mapper related uevent
// if udev event is valid then it return non-empty string that contains
// new mapper device name (e.g. /dev/mapper/name)
func handleMapperDeviceUevent(ev *uevent.Uevent) error {
devName := ev.Vars["DEVNAME"]
func handleMapperDeviceUevent(ev netlink.UEvent) error {
devName := ev.Env["DEVNAME"]

major, err := strconv.Atoi(ev.Vars["MAJOR"])
major, err := strconv.Atoi(ev.Env["MAJOR"])
if err != nil {
return fmt.Errorf("udev['MAJOR']: %v", err)
}
minor, err := strconv.Atoi(ev.Vars["MINOR"])
minor, err := strconv.Atoi(ev.Env["MINOR"])
if err != nil {
return fmt.Errorf("udev['MAJOR']: %v", err)
}
Expand Down

0 comments on commit a9475f7

Please sign in to comment.