|
8 | 8 | "strings"
|
9 | 9 | "time"
|
10 | 10 |
|
| 11 | + ns "github.com/containernetworking/plugins/pkg/ns" |
11 | 12 | log "github.com/sirupsen/logrus"
|
12 | 13 |
|
13 | 14 | util "github.com/linkerd/linkerd2-proxy-init/internal/util"
|
@@ -229,28 +230,59 @@ func makeMultiportDestinations(portsToIgnore []string) [][]string {
|
229 | 230 | }
|
230 | 231 |
|
231 | 232 | func executeCommand(firewallConfiguration FirewallConfiguration, cmd *exec.Cmd) ([]byte, error) {
|
232 |
| - if firewallConfiguration.NetNs != "" { |
233 |
| - // BusyBox's `nsenter` needs `--` to separate nsenter arguments from the |
234 |
| - // command. |
235 |
| - // |
236 |
| - // See https://github.com/rancher/k3s/issues/1434#issuecomment-629315909 |
237 |
| - nsArgs := fmt.Sprintf("--net=%s", firewallConfiguration.NetNs) |
238 |
| - args := append([]string{nsArgs, "--"}, cmd.Args...) |
239 |
| - cmd = exec.Command("nsenter", args...) |
240 |
| - } |
| 233 | + // Always log the command to apply for tracing purposes |
241 | 234 | log.Info(cmd.String())
|
242 | 235 |
|
| 236 | + // Short out early if we are just simulating the network |
243 | 237 | if firewallConfiguration.SimulateOnly {
|
244 | 238 | return nil, nil
|
245 | 239 | }
|
246 | 240 |
|
247 |
| - out, err := cmd.CombinedOutput() |
| 241 | + // Helper for reusing code when actually calling out to the command |
| 242 | + doCommand := func() ([]byte, error) { |
| 243 | + out, err := cmd.CombinedOutput() |
248 | 244 |
|
249 |
| - if len(out) > 0 { |
250 |
| - log.Infof("%s", out) |
| 245 | + // Log out the output, if any |
| 246 | + if len(out) > 0 { |
| 247 | + log.Infof("%s", out) |
| 248 | + } |
| 249 | + |
| 250 | + return out, err |
251 | 251 | }
|
252 | 252 |
|
253 |
| - return out, err |
| 253 | + // If we need to run within a target network namespace, then wrap the command |
| 254 | + // in that namespace. |
| 255 | + // |
| 256 | + // Note: Network namespace switching is very volatile in Go. Care should be taken |
| 257 | + // to ensure that all namespaced commands be wrapped in `targetNamespace.Do`, as explained in |
| 258 | + // the link below. |
| 259 | + // |
| 260 | + // See: https://pkg.go.dev/github.com/containernetworking/plugins/pkg/ns#readme-do-the-recommended-thing |
| 261 | + if firewallConfiguration.NetNs != "" { |
| 262 | + // Fetch the target net namespace, ensuring that it exists |
| 263 | + netNs, err := ns.GetNS(firewallConfiguration.NetNs) |
| 264 | + if err != nil { |
| 265 | + log.Errorf("could not switch to target network namespace \"%s\": %s", firewallConfiguration.NetNs, err.Error()) |
| 266 | + return nil, err |
| 267 | + } |
| 268 | + |
| 269 | + // Actually run the command in the namespace |
| 270 | + // Note: Try to keep this code short! Goroutine switches might cause the |
| 271 | + // namespace to change... |
| 272 | + // |
| 273 | + // Note: Result needs to be defined here since `netNs.Do` only returns |
| 274 | + // an error. |
| 275 | + result := make([]byte, 0) |
| 276 | + err = netNs.Do(func(_ ns.NetNS) error { |
| 277 | + result, err = doCommand() |
| 278 | + |
| 279 | + return err |
| 280 | + }) |
| 281 | + |
| 282 | + return result, err |
| 283 | + } else { |
| 284 | + return doCommand() |
| 285 | + } |
254 | 286 | }
|
255 | 287 |
|
256 | 288 | func (fc FirewallConfiguration) makeIgnoreUserID(chainName string, uid int, comment string) *exec.Cmd {
|
|
0 commit comments