On Dec 28, 2010, at 11:43 AM, Silvan Calarco wrote:

> On Tuesday 28 December 2010 17:01:50 Jeff Johnson wrote:
>> On Dec 28, 2010, at 10:38 AM, Silvan Calarco wrote:
>>> Hi,
>>> I'm trying to port to rpm 5.2.1 an application that was previously made
>>> for rpm 4.4.9.
>>> 
>>> The application used to read the header with the following code:
>>>         FD_t fd;
>>>         fd = fdOpen(headerFile, O_RDONLY, 0);
>>> 
>>> but with rpm 5.2.1 build stops with the error in the subject.
>> 
>> The solution here is to use Fopen(), not fdOpen().
> 
> Ok, I replaced also a fdFileno() with Fileno() and the build completed 
> successfully. Now I just have to fix a list of warnings like these:
> 
> rpmfunctions.c:124:21: warning: pointer targets in passing argument 3 of 
> ‘headerGetEntry’ differ in signedness
> /usr/include/rpm/rpmlib.h:119:19: note: expected ‘hTYP_t’ but argument is of 
> type ‘int *’
> rpmfunctions.c:124:21: warning: pointer targets in passing argument 5 of 
> ‘headerGetEntry’ differ in signedness
> /usr/include/rpm/rpmlib.h:119:19: note: expected ‘hCNT_t’ but argument is of 
> type ‘int *’
> 

Hmmm ... that's some really old code ...

hTYP_t/hCNT_t were an early attempt at typedef's in RPM.

In rpm-5.x there's a union (what used to be the 4th arg in headerGetEntry as a 
void **)
contained in rpmdb/rpmtag.h:

        union rpmDataType_u {
        /*...@null@*/
            void * ptr;
            rpmuint8_t * ui8p;          /*!< RPM_UINT8_TYPE | RPM_CHAR_TYPE */
            rpmuint16_t * ui16p;        /*!< RPM_UINT16_TYPE */
            rpmuint32_t * ui32p;        /*!< RPM_UINT32_TYPE */
            rpmuint64_t * ui64p;        /*!< RPM_UINT64_TYPE */
        /*...@relnull@*/
            const char * str;           /*!< RPM_STRING_TYPE */
            unsigned char * blob;       /*!< RPM_BIN_TYPE */
            const char ** argv;         /*!< RPM_STRING_ARRAY_TYPE */
            HE_t he;
        };

and hTYP_t (the 3rd arg to headerGetEntry) and hCNT_t (the 5th argument) have 
all
been bundled into a structure
        struct _HE_s {
            rpmTag tag;
            rpmTagType t;
        /*...@owned@*/ /*...@null@*/
            rpmTagData p;
            rpmTagCount c;
            int ix;
            unsigned int freeData       : 1;
            unsigned int avail          : 1;
            unsigned int append         : 1;
        };

Note: the ix and the bit fields are only used by headerPut().

SO instead of headerGetEntry() the replacement becomes
something like this (this is my paradigm anyways, adjust to tate
if you dislike using alloca):

    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));

    he->tag = RPMTAG_NAME;
    if (headerGet(h, he, 0) && he->t == RPM_STRING_TYPE && he->c == 1)
        *np = xstrdup(he->p.str);
    else
        *np = NULL;
    he->p.ptr = _free(he->p.ptr); 

The above snippet is in rpmdb/hdrnvr.c and is a bit more anal
about checking type and count than necessary.

But do note the final
    he->p.ptr = _free(he->p.ptr);
(the _free is just a static inline so I don't have to worry about
NULL pointers passed to free, and the assignment is just so that
the original pointer cannot be accidentally reused == just my
coding fetishes, use free(3) however you wish).

The programming rule (and the single biggest change with rpm-5.x) is
        All data returned by headerGet() must be free'd.

        



>>> Is that a headers problem or is it intended that I should use a different
>>> approach?
>> 
>> Different approach. But you can call through the FDIO_s vector to
>> _fopen still if necessary, I don't recall any changes there.
> 
> Ok. I'm just doing a "blind" port for now and will see if it works.
> 
> To avoid patching a lot of sources and autotools I've also made a symlink 
> /usr/include/rpm/rpmlib.h pointing to /usr/include/rpm/rpm4compat.h, quite 
> ugly but it worked.
> 

rpm4compat.h "works" surprisngly "well" (imho). But I'll
be happy to assist getting rid of the need for using
rpm4compat.h in any code. I can do RPM ports in my sleep,
and I're _REALLY_ like not to have to carry around an ancient
API forevermore.

>> The intent is a stdio-like interface, with Fopen instead of fopen, Fread
>> instead of fread.
>> 
>> Note that the first argument to Fopen can be a URI too. That "works" for
>> full content reads on ftp:// and (mostly, no redirects, no proxies, ...)
>> on http:// in rpm-5.2.1.
> 
> Good.
> 
>>> Thanks for your help!
>> 
>> np. I can/will help with any porting issues.
> 
> Thank you also for helping in 4.4.9 -> 5.2.1 upgrade. Next step will be 
> upgrading to 5.3.6 and possibly integrating some openmamba patches upstream.
> 

Cool. You might want to watch Per Oyvind's success/failures in Mandriva Cooker.
AFAICT most of the pieces are in place for a rpm-4.6.1 -> rpm-5.3.6 upgrade.

The jump from rpm-5.2.1 -> rpm-5.3.6 is a bit easier, but still has
the _rpmmi_usermem and mmap PROT_READ issue. Unlike rpm-5.2.1, rpm-5.3.6
has removed the signature/digest check when reading rpmdb header's, and
so disabling PROT_READ gets snarled up with security issues.

(aside)
The RPM security issues are rather ill specified: noo ne has ever bothered
to define what threat model(s) apply to an rpmdb. Verifying signatures/digests
whenever a header is read/written to an rpmdb (and PROT_READ protection) is
likely hirrendously over-engineered and simply doesn't matter.

But with the onslaught of SELinux "collections" and MeeGo MSSF and IMA-EVM
all starting to use *.rpm packaging, well ...

        Someone ought to start thinking through RPM's "threat model" more
        carefully and precisely.

hth

73 de Jeff______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
Developer Communication List                        rpm-devel@rpm5.org

Reply via email to