📄 0232-0234.html
字号:
<HTML>
<HEAD>
<TITLE>Maximum RPM (RPM):Making a Package That Can Build Anywhere:EarthWeb Inc.-</TITLE>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<SCRIPT>
<!--
function displayWindow(url, width, height) {
var Win = window.open(url,"displayWindow",'width=' + width +
',height=' + height + ',resizable=1,scrollbars=yes');
}
//-->
</SCRIPT>
</HEAD>
-->
<!-- ISBN=0672311054 //-->
<!-- TITLE=Maximum RPM (RPM)//-->
<!-- AUTHOR=Edward Bailey//-->
<!-- PUBLISHER=Macmillan Computer Publishing//-->
<!-- IMPRINT=Sams//-->
<!-- CHAPTER=16 //-->
<!-- PAGES=0225-0236 //-->
<!-- UNASSIGNED1 //-->
<!-- UNASSIGNED2 //-->
<P><CENTER>
<a href="0229-0231.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0235-0236.html">Next</A>
</CENTER></P>
<A NAME="PAGENUM-232"><P>Page 232</P></A>
<!-- CODE //-->
<PRE>
+ umask 022
Executing: %prep
+ cd /home/ed/mybuild/BUILD
+ cd /home/ed/mybuild/BUILD
+ rm -rf cdplayer-1.0
+ gzip -dc /home/ed/mybuild/SOURCES/cdplayer-1.0.tgz
+ tar -xvvf -
drwxrwxr-x root/users 0 Aug 20 20:58 1996 cdplayer-1.0/
-rw-r--r-- root/users 17982 Nov 10 01:10 1995 cdplayer-1.0/COPYING
...
+ cd /home/ed/mybuild/BUILD/cdplayer-1.0
+ chmod -R a+rX,g-w,o-w .
+ exit 0
Executing: %build
+ cd /home/ed/mybuild/BUILD
+ cd cdplayer-1.0
+ make
gcc -Wall -O2 -c -I/usr/include/ncurses cdp.c
...
Executing: %install
+ cd /home/ed/mybuild/BUILD
+ make ROOT=/home/ed/mybuildroot/cdplayer install
install -m 755 -o 0 -g 0 -d /home/ed/mybuildroot/cdplayer/usr/local/bin/
install: /home/ed/mybuildroot/cdplayer: Operation not permitted
install: /home/ed/mybuildroot/cdplayer/usr: Operation not permitted
install: /home/ed/mybuildroot/cdplayer/usr/local: Operation not permitted
install: /home/ed/mybuildroot/cdplayer/usr/local/bin: Operation not permitted
install: /home/ed/mybuildroot/cdplayer/usr/local/bin/: Operation not permitted
make: *** [install] Error 1
Bad exit status
%
</PRE>
<!-- END CODE //-->
<P>Things started out pretty well. The %prep section of the spec file unpacked the sources into
the new build area, as did the %build section. The build was proceeding normally in the
user-specified build area, and root access was not required. In the
%install section, however, things started to fall apart. What happened?
</P>
<P>Take a look at that install command. The two options,
-o 0 and -g 0, dictate that the directories to be created in the build root are to be owned by the root account. Since the user
performing this build did not have root access, the install failed, and rightly so.
</P>
<P>Okay, let's remove the offending options and see where that gets us. Here's the
install section of the makefile after our modifications:
</P>
<!-- CODE //-->
<PRE>
install: cdp cdp.1.Z
install -m 755 -d $(ROOT)/usr/local/bin/
install -m 755 cdp $(ROOT)/usr/local/bin/cdp
rm -f $(ROOT)/usr/local/bin/cdplay
ln -s ./cdp $(ROOT)/usr/local/bin/cdplay
install -m 755 -d $(ROOT)/usr/local/man/man1/
install -m 755 cdp.1 $(ROOT)/usr/local/man/man1/cdp.1
</PRE>
<!-- END CODE //-->
<P>We'll spare you having to read through another build, but this time it completed
successfully. Now, let's put our sysadmin hat on and install the newly built package:
</P>
<A NAME="PAGENUM-233"><P>Page 233</P></A>
<!-- CODE SNIP //-->
<PRE>
# rpm -ivh cdplayer-1.0-1.i386.rpm
cdplayer ##################################################
#
</PRE>
<!-- END CODE SNIP //-->
<P>Well, that was easy enough. Let's take a look at some of the files and make sure
everything looks okay. We know there are some files installed in
/usr/local/bin, so let's check those:
</P>
<!-- CODE SNIP //-->
<PRE>
# ls -al /usr/local/bin
-rwxr-xr-x 1 ed ed 40739 Sep 13 20:16 cdp*
lrwxrwxrwx 1 ed ed 47 Sep 13 20:34 cdplay -> ./cdp*
#
</PRE>
<!-- END CODE SNIP //-->
<P>Looks pretty good. Wait a minute! What's up with the owner and group? The answer is
simple: User ed ran the build, which executed the makefile, which ran
install, which created the files. Since ed created the files, they are owned by him.
</P>
<P>This brings up an interesting point. Software must be installed with very specific file
ownership and permissions. But a nonroot user can't create files that are owned by anyone other
than himself or herself. What is a nonroot user to do?
</P>
<H3><A NAME="ch16_ 8">
16.3. Specifying File Attributes
</A></H3>
<P>In cases where the package builder cannot create the files to be packaged with the proper
ownership and permissions, the %attr macro can be used to make things right.
</P>
<H4><A NAME="ch16_ 9">
16.3.1. %attr: How Does It Work?
</A></H4>
<P>
The %attr macro has the following format:
</P>
<!-- CODE SNIP //-->
<PRE>
%attr(<mode>, <user>, <group>) <file>
</PRE>
<!-- END CODE SNIP //-->
<UL>
<LI>
<mode> is represented in traditional numeric fashion.
<LI>
<user> is specified by the login name of the user. Numeric UIDs are not used,
for reasons we'll explore in a moment.
<LI>
<group> is specified by the group's name, as entered in
/etc/group. Numeric GIDs are not used, either. Yes, we'll be discussing that, too!
<LI>
<file> represents the file. Shell-style globbing is supported.
</UL>
<P>There are a couple other wrinkles to using the
%attr macro. If a particular file attribute
doesn't need to be specified, that attribute can be replaced with a dash
(-), and %attr will not change it. Say, for instance, that a package's files are installed with the permissions correctly set,
as they almost always are. Instead of having to go to the trouble of entering the permissions
for each and every file, each file can have the same
%attr:
</P>
<!-- CODE SNIP //-->
<PRE>
%attr(-, root, root)
</PRE>
<!-- END CODE SNIP //-->
<P>This works for user and group specifications, as well.
</P>
<A NAME="PAGENUM-234"><P>Page 234</P></A>
<P>The other wrinkle is that although we've been showing the three file attributes separated
by commas, in reality they could be separated by spaces as well. Whichever delimiter you
choose, it pays to be consistent throughout a spec file.
</P>
<P>Let's fix up cdplayer with a liberal sprinkling of
%attrs. Here's what the %files list looks like after we've had our way with it:
</P>
<!-- CODE //-->
<PRE>
%files
%attr(-, root, root) %doc README
%attr(4755, root, root) /usr/local/bin/cdp
%attr(-, root, root) /usr/local/bin/cdplay
%attr(-, root, rot) /usr/local/man/man1/cdp.1
</PRE>
<!-- END CODE //-->
<P>A couple points are worth noting here. The line for
README shows that multiple macros can be used on a line—in this case, one to set file attributes and one to mark the file as being
documentation. The %attr for /usr/local/bin/cdp declares the file to be
setuid root. If it sends a shiver down your spine to know that anybody can create a package that will run
setuid root when installed on your system, good! Just because RPM makes it easy to install software
doesn't mean that you should blindly install every package you find.
</P>
<P>A single RPM command can quickly point out areas of potential problems and should be
issued on any package file whose creators you don't trust:
</P>
<!-- CODE //-->
<PRE>
% rpm -qlvp ../RPMS/i386/cdplayer-1.0-1.i386.rpm
drwxr-xr-x- root root 1024 Sep 13 20:16 /usr/doc/cdplayer-1.0-1
-rw-r--r-- root root 1085 Nov 10 01:10 /usr/doc/cdplayer-1.0-1/README
-rwsr-xr-x- root root 40739 Sep 13 21:32 /usr/local/bin/cdp
lrwxrwxrwx- root root 47 Sep 13 21:32 /usr/local/bin/cdplay -> ./cdp
-rwxr-xr-x- root root 4550 Sep 13 21:32 /usr/local/man/man1/cdp.1
%
</PRE>
<!-- END CODE //-->
<P>Sure enough. There's that setuid root file. In this case we trust the package builder, so
let's install it:
</P>
<!-- CODE //-->
<PRE>
# rpm -ivh cdplayer-1.0-1.i386.rpm
cdplayer ##################################################
group rot does not exist - using root
#
</PRE>
<!-- END CODE //-->
<P>What's this about group rot? Looking back at the
rpm -qlvp output, you can see that
/usr/local/man/man1/cdp.1 has a bogus group. Looking back even further, it's there in the
%attr for that file. Must have been a typo. We could pretend that RPM used advanced artificial
intelligence technology to come to the same conclusion as we did and made the appropriate
change, but, in reality, RPM simply used the only group identifier it could count on:
root. RPM will do the same thing if it can't resolve a user specification.
</P>
<P>Let's look at some of the files the package installed, including that worrisome
setuid root file:
</P>
<!-- CODE //-->
<PRE>
# ls /usr/local/bin
total 558
-rwsr-xr-x 1 root root 40739 Sep 13 21:32 cdp*
lrwxrwxrwx 1 root root 47 Sep 13 21:36 cdplay -> ./cdp*
#
</PRE>
<!-- END CODE //-->
<P><CENTER>
<a href="0229-0231.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0235-0236.html">Next</A>
</CENTER></P>
</td>
</tr>
</table>
<!-- begin footer information -->
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -