Skip to content

Latest commit

 

History

History
31 lines (21 loc) · 2.26 KB

README.md

File metadata and controls

31 lines (21 loc) · 2.26 KB

1Password LD_PRELOAD inotify Workaround - inotify_add_watch

Background

1Password has a thread/async loop which listens for inotify messages on a number of files, including its own executable. It calls inotify_add_watch for the 1password binary with the mask 0xfce which is (IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF). If this inotify event triggers, 1Password will exit. This is to prevent incorrect JavaScript code from being loaded when the application is updated (see https://1password.community/discussion/138445/application-exits-on-rpm-ostree-update).

On a rpm-ostree deployment, RPM packages which deploy to /opt are actually deployed to /usr/lib/opt and a symlink is created in /var/opt. The files in /usr/lib/opt are immutable because /usr is usually mounted read-only. However, on btrfs — and likely other filesystems — a read-only mount does not prevent updates to the inode, particularly updates to the link count which is updated when hard links are created (this also resets the ctime). Since ostree checks out objects as hard links (similar to git), whenever a new commit is created with duplicate files the link count of /opt/1Password/1password can change and cause the program to quit. In practice, 1Password quits whenever rpm-ostree is called to upgrade or change packages.

Workaround

From the background, we know that changes to the file attributes — particularly the link count — is triggering the inotify event which quits 1Password. The workaround is to remove the IN_ATTRIB bit from the mask provided to inotify_add_watch() when the filepath ends with /1password.

We do this by creating a shared object file which when loaded into the binary with LD_PRELOAD or patchelf will hook inotify_add_watch().

Build and run

# Build the shared object
make
# copy the shared object to /opt/1Password/
sudo make install
# Run/test the injection
LD_PRELOAD=$PWD/1p-ldpreload.so /opt/1Password/1password
# If it works, make the injection permanent
patchelf --add-needed '1p-ldpreload.so' /opt/1Password/1password

Packaging

The 1password-ostree-workaround.spec file can be used to build a RPM file for this project. Use rpmbuild or fedpkg to build it.