Skip to content

[action] [PR:4365] Fix migrate_sonic_packages() crash on symlink resolv.conf#4380

Merged
mssonicbld merged 1 commit intosonic-net:202511from
mssonicbld:cherry/202511/4365
Mar 20, 2026
Merged

[action] [PR:4365] Fix migrate_sonic_packages() crash on symlink resolv.conf#4380
mssonicbld merged 1 commit intosonic-net:202511from
mssonicbld:cherry/202511/4365

Conversation

@mssonicbld
Copy link
Copy Markdown
Collaborator

What I did

Fixed sonic-installer install failing during migrate_sonic_packages() when /etc/resolv.conf in the new image is a symlink to /run/resolvconf/resolv.conf.

The failure occurs because the cp command at main.py:386 follows the symlink through the overlay mount. Since the symlink target is an absolute path, it resolves to the host's /run/resolvconf/resolv.conf — the same file as the source. cp detects same source and destination inode and exits with:

cp: '/etc/resolv.conf' and '/tmp/image-<version>-fs/etc/resolv.conf' are the same file

This was introduced by the build_debian.sh change that replaced touch with ln -sf /run/resolvconf/resolv.conf for /etc/resolv.conf in the image filesystem.

How I did it

Check whether /etc/resolv.conf in the chroot is a symlink or a regular file, and handle each case appropriately:

  • Symlink (images with resolvconf package installed): Read the symlink target via readlink (e.g. /run/resolvconf/resolv.conf), then create the target file inside the chroot with the host's DNS content. The symlink then resolves correctly inside the chroot. This avoids touching the symlink itself, so the overlay upper dir's etc/resolv.conf is never modified and the new image boots with the symlink intact. No cleanup is needed — the target lives under /run, which is a tmpfs recreated at every boot.

  • Regular file (images without resolvconf, or where the build process explicitly creates a regular file via touch): Overwrite directly with the host's DNS content. No backup/restore is needed — the original file is empty (cleared during build), and after reboot the resolv-config service reconfigures DNS from CONFIG_DB.

The previous backup-overwrite-restore pattern has been removed since it is unnecessary in both cases.

How to verify it

  1. Start with a switch running an image where /etc/resolv.conf is a symlink:

    # Confirm symlink exists
    ls -la /etc/resolv.conf
    # Expected: /etc/resolv.conf -> /run/resolvconf/resolv.conf
    
    # Ensure only one image is installed (clean state)
    sudo sonic-installer list
    # If the target image is already present, remove it:
    sudo sonic-installer remove <target-image> -y
  2. Run sonic-installer install with an image that also has the symlink:

    sudo sonic-installer install <image-path> -y
  3. Verify:

    • Installation completes without cp: ... are the same file error
    • sonic-installer list shows the new image as default
    • After reboot, /etc/resolv.conf is still a symlink to /run/resolvconf/resolv.conf
    • DNS resolution works

Signed-off-by: Sonic Build Admin sonicbld@microsoft.com

Previous command output (if the output of a command-line utility has changed)

New command output (if the output of a command-line utility has changed)

<!--
    Please make sure you've read and understood our contributing guidelines:
    https://github.com/Azure/SONiC/blob/gh-pages/CONTRIBUTING.md

    ** Make sure all your commits include a signature generated with `git commit -s` **

    If this is a bug fix, make sure your description includes "closes #xxxx",
    "fixes #xxxx" or "resolves #xxxx" so that GitHub automatically closes the related
    issue when the PR is merged.

    If you are adding/modifying/removing any command or utility script, please also
    make sure to add/modify/remove any unit tests from the tests
    directory as appropriate.

    If you are modifying or removing an existing 'show', 'config' or 'sonic-clear'
    subcommand, or you are adding a new subcommand, please make sure you also
    update the Command Line Reference Guide (doc/Command-Reference.md) to reflect
    your changes.

    Please provide the following information:
-->

#### What I did

Fixed `sonic-installer install` failing during `migrate_sonic_packages()` when `/etc/resolv.conf` in the new image is a symlink to `/run/resolvconf/resolv.conf`.

The failure occurs because the `cp` command at `main.py:386` follows the symlink through the overlay mount. Since the symlink target is an absolute path, it resolves to the **host's** `/run/resolvconf/resolv.conf` — the same file as the source. `cp` detects same source and destination inode and exits with:

```
cp: '/etc/resolv.conf' and '/tmp/image-<version>-fs/etc/resolv.conf' are the same file
```

This was introduced by the `build_debian.sh` change that replaced `touch` with `ln -sf /run/resolvconf/resolv.conf` for `/etc/resolv.conf` in the image filesystem.

#### How I did it

Check whether `/etc/resolv.conf` in the chroot is a symlink or a regular file, and handle each case appropriately:

- **Symlink** (images with `resolvconf` package installed): Read the symlink target via `readlink` (e.g. `/run/resolvconf/resolv.conf`), then create the target file inside the chroot with the host's DNS content. The symlink then resolves correctly inside the chroot. This avoids touching the symlink itself, so the overlay upper dir's `etc/resolv.conf` is never modified and the new image boots with the symlink intact. No cleanup is needed — the target lives under `/run`, which is a tmpfs recreated at every boot.

- **Regular file** (images without `resolvconf`, or where the build process explicitly creates a regular file via `touch`): Overwrite directly with the host's DNS content. No backup/restore is needed — the original file is empty (cleared during build), and after reboot the `resolv-config` service reconfigures DNS from CONFIG_DB.

The previous backup-overwrite-restore pattern has been removed since it is unnecessary in both cases.

#### How to verify it

1. Start with a switch running an image where `/etc/resolv.conf` is a symlink:
   ```bash
   # Confirm symlink exists
   ls -la /etc/resolv.conf
   # Expected: /etc/resolv.conf -> /run/resolvconf/resolv.conf

   # Ensure only one image is installed (clean state)
   sudo sonic-installer list
   # If the target image is already present, remove it:
   sudo sonic-installer remove <target-image> -y
   ```

2. Run `sonic-installer install` with an image that also has the symlink:
   ```bash
   sudo sonic-installer install <image-path> -y
   ```

3. Verify:
   - Installation completes without `cp: ... are the same file` error
   - `sonic-installer list` shows the new image as default
   - After reboot, `/etc/resolv.conf` is still a symlink to `/run/resolvconf/resolv.conf`
   - DNS resolution works

Signed-off-by: Sonic Build Admin <sonicbld@microsoft.com>

#### Previous command output (if the output of a command-line utility has changed)

#### New command output (if the output of a command-line utility has changed)
@mssonicbld
Copy link
Copy Markdown
Collaborator Author

Original PR: #4365

@mssonicbld
Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@mssonicbld mssonicbld merged commit b921a54 into sonic-net:202511 Mar 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant