Querying and Verifying With rpm
In one line
rpm is a query tool before it is an install tool. And rpm -V is a powerful audit tool that tells you what has happened to the system.
Why this exists
In an outage or a suspected intrusion, what matters more than "the package is installed" is whether the installed files are the same as in the original package. If you look up a file's owning package, its install scripts, the list of configuration files, and the digest differences directly from the rpm database, you can narrow the scope of changes before reinstalling blindly. However, for an incident in which even the rpm database cannot be trusted, you also have to compare against a separate trustworthy manifest.
How it works
Query (-q)
rpm -qa # 설치된 전부
rpm -qa | wc -l
rpm -qi httpd # 상세 정보
rpm -ql httpd # 설치한 파일 목록
rpm -qc httpd # 설정 파일만
rpm -qd httpd # 문서 파일만
rpm -qf /usr/sbin/httpd # 이 파일의 주인
rpm -q --changelog httpd | head
rpm -q --scripts httpd # 설치 스크립트(%pre/%post 등)
rpm -q --requires httpd
rpm -q --provides httpd
If you put -p before a file, it queries an .rpm file that is not installed.
rpm -qpi ./labhub-tool-1.0-1.noarch.rpm
rpm -qpl ./labhub-tool-1.0-1.noarch.rpm
rpm -qp --qf '%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n' ./x.rpm
Pulling out only the fields you want with --qf (queryformat) is the key to automation. Handling epoch needs a ternary notation.
rpm -qp --qf '%{NAME}\t%|EPOCH?{%{EPOCH}}:{0}|\t%{VERSION}\t%{RELEASE}\t%{ARCH}\n' ./x.rpm
A package with no epoch shows the field as (none), so this notation fills in 0. The file name does not include the epoch, so you must write this value in the manifest.
Verification (-V)
rpm -V httpd
rpm -Va | head # 전체 검증 (느리다)
The output has a form like SM5DLUGTP c /etc/httpd/conf/httpd.conf.
| Character | Meaning |
|---|---|
S |
File size differs |
M |
Mode (permissions/type) differs |
5 |
File content digest differs (historically from the MD5 indicator) |
D |
Device number differs |
L |
Symlink target differs |
U / G |
Owner/group differs |
T |
mtime differs |
P |
capabilities differ |
c (second column) |
Configuration file marker |
It is normal for a configuration file (c) to have changed. An administrator probably edited it. But if a binary has changed, you must investigate — it means either an intrusion or that someone overwrote it by hand.
Signature verification
rpm --checksig ./x.rpm
rpmkeys --checksig ./x.rpm # 권장 표기
rpmkeys --import /etc/pki/rpm-gpg/RPM-GPG-KEY-...
rpmkeys --list
digests signatures OK is what should appear. If the key is not registered, only the digest passes and the signature stays unverifiable, and it is easy to misread that as "passed". It has to become a habit to check with rpmkeys --list before the check that the key is registered.
Building a package
~/rpmbuild/
SPECS/ labhub-tool.spec
SOURCES/ labhub-tool-1.0.tar.gz
BUILD/ (빌드 중간 산출물)
BUILDROOT/ (가상의 설치 루트)
RPMS/ (완성된 바이너리 rpm)
SRPMS/ (소스 rpm)
The skeleton of a spec file.
Name: labhub-tool
Version: 1.0
Release: 1%{?dist}
Summary: 예제 도구
License: MIT
Source0: %{name}-%{version}.tar.gz
BuildArch: noarch
Requires: coreutils
%description
...
%prep
%setup -q
%build
make
%install
make install DESTDIR=%{buildroot} PREFIX=/usr
%files
/usr/bin/labhub-tool
%changelog
* Sat Aug 15 2026 LabHub <lab@labhub.local> - 1.0-1
- 최초 패키징
If a file not listed in %files is in the buildroot, the build fails. "Installed (but unpackaged) files found" is that message. Conversely, it also fails if you list something in %files that does not actually exist. This strictness keeps the package contents accurate.
rpmbuild -ba ~/rpmbuild/SPECS/labhub-tool.spec # 바이너리 + 소스 rpm
rpmbuild -bb ... # 바이너리만
rpm2cpio x.rpm | cpio -idmv # 설치 없이 내용 풀기
What it looks like in the field
Finding traces of intrusion with rpm -Va. When the system looks wrong, you use this command to find tampered binaries. However, the rpm database itself may have been tampered with, so for certainty you have to compare against a trustworthy copy.
What you will do in the next lab
You query and verify with rpm, and build a package yourself from a spec file and even install it.