Submind YouTube summaries
Thumbnail for Flock 2025 Specfile Library + NoRPM

Flock 2025 Specfile Library + NoRPM

Watch on YouTube

Video summary

The video introduces "specfile," a Python library designed specifically for parsing and modifying RPM spec files with a strong emphasis on safety and minimal diffs. Unlike standard tools that might alter files aggressively, this library ensures that any changes made to someone else's spec file result in the smallest possible difference, which is crucial for maintaining project integrity. The presenter demonstrates various capabilities of the library, such as automatically bumping release numbers, adding changelog entries with specific metadata like author and date, and manipulating different sections of a spec file. A key feature highlighted is its ability to intelligently update version numbers even when they are defined using complex macros, attempting to replace macro definitions directly rather than just overwriting values, which works effectively in over 90% of cases. The second part of the talk shifts focus to the inherent security risks and architectural headaches associated with building RPM packages, particularly when dealing with untrusted source code from the internet. The speaker explains that blindly executing shell scripts or Lua code found within spec files can compromise a system, even if isolation tools like Mock are used, as these tools operate on a best-effort basis and may not fully prevent privilege escalation or data leakage. To mitigate these risks while still allowing users to build custom packages from GitHub or other sources, the presenters discuss strategies such as caching sources in isolated virtual machines and using a proxy Git repository. They also introduce "noRPM," a pure Python microprocessor for RPM that aims to parse spec files without relying on the full RPM binary toolchain, offering a safer alternative for non-RPM distributions or environments where executing arbitrary build scripts is too dangerous. A significant portion of the discussion addresses the limitations and future improvements needed in both the existing ecosystem and new tools like noRPM. The speakers note that while noRPM successfully handles basic tasks like extracting version and release numbers for a vast majority of Fedora spec files, it currently lacks support for advanced features such as dynamic build requirements or complex macro evaluations found in full RPM builds. They propose potential future enhancements to the RPM toolchain itself, including a new low-privilege mode that would ignore unknown spec file syntaxes rather than failing outright, thereby preventing crashes when encountering new directives. The overarching conclusion is that developers should strive to keep their spec files as simple and static as possible, avoiding dynamic content like shell scripts in the preamble, to ensure compatibility with safer parsing tools and to prevent security vulnerabilities during the build process.
Read the full video transcript
Okay. So, hello everyone. Welcome to the second day of vlog. Uh, my name is Nicolola. This is Pavl. >> Hey. >> And we will have actually two talks in one. So, let's start with mine. And, uh, yeah, we have we don't have a lot of time. So I will just >> yeah kind of lightning talking today. So enjoy. >> Okay. So this is about spec file library. I don't know if you heard about it if not it is a Python library that's uh uh Python library for paring and modifying spec files. The emphasis is on modification because that's why we designed it uh in Uh also it means that it's not very fast because like function of over speed basically. Uh one of the main goals is that the changes that you make should result in a minimal diff. So if you edit someone else's spec file, uh the changes should be minimal. Uh it's packaged for Federa and the PAL and you it is used by petit uh and also for example cop and some other projects. Uh so from now on I will I will be showing showing code samples. So [cough and clears throat] uh this one should be pretty self-explanatory I hope. Uh let me just talk about the bottom segment. uh if you maybe you can see from the from the code itself uh it should bump the release in the spec file and add a change lock entry. So basically what RPM def bump spec does uh so the main tags are exposed as properties. So in this case we are using expanded release which is the value of the release tech with all macros expanded. Uh this is a pretty naive example because it expects the result to be a number but uh it's just for demonstration purposes. So the value is incremented and converted to string and returned back to or assigned back to release. Uh and then there is a method for adding a change entry. Uh in this case we are specifying only the text of the entry but you can also specify all other uh all other data like uh author or date etc. Uh okay let's move on. Okay. So, uh in this case, uh we want to work with with sections. Uh this example should uh basically convert from change log to auto change log. So uh there is the sections method that returns a context manager and in the target variable uh it behaves as a list of sections and within the context of the context manager you can modify it you can work with it as as with list and the changes will be propagated back once the context is exited. Uh you can also access the sections by name. So in this case change lock and the section again behaves as a list of lines. So here we just uh copy the entire change log and replace it with just one line uh that is how to change log and then we are just dumping the uh original content to the change lock file. So another example in the previous one we were accessing the section by name now we are iterating over all sections but uh this example should print just or it should print all request tax in a spec file. So we are interesting only interested only in packet sections uh skipping all else and then we use text method that returns a list of text or again a con context manager that behaves as a list of texts and we just filter the request once and paint the all the details. Okay, so that was pretty much it. There is or of course a lot of a lot more but I want to show you something more interesting maybe. So if you have a spec file like this and you want to update the version and if the version is uh defined using macros then if you if you just would as if you would just assign the version to the version property it would end up like this. This would be the div and that's probably not what you want or not what the maintainers want. So you can do this instead. There is this update tech method that tries to if possible it tries to actually replace the values of the macro definitions instead. Uh the algorithm behind it is not very complex. It's actually quite simple. it just uh uh splits the string uh on some element and then tries to match the individual parts to the micro definitions. So, it doesn't work in all cases, but I would say it uh well, I actually measured it, but uh I'm not sure about the exact number, but I think it was about um o over 90% of spec files that work. And uh it is possible to do this. Uh if it if it wasn't possible, then the version would just be replaced as before. And this is my last last slide. So I want to talk about macros and conditions. So spec file uses RPM for uh expanding macros and eval evaluating expressions in conditions. Uh you can also define your own macros by uh yeah by passing them to the constructor and you can expand any macro or expression uh using the expand method. And as [clears throat] for conditions, so in this case you have two epoch tags. You would probably if you would be modifying the spec file, you would probably want to change maybe all of them or both of them. But you are if you are interesting only interested in the value of the one that would be the correct one let's say. So that would be valid in uh in case username is defined then there is a valid property of the tech object and that is true only in the two branch of the condition or if there are nested conditions it would be true only for the text that are in two branches of all of them. Yeah that's pretty much it. So I'm not sure if you have any questions. We have probably a couple of minutes or I can pass it to Pavl and then we can answer questions at the end. And there's there are some links. So I encourage you to check this because like I said this was just a quick overview what the library can do and yes. I guess you should say it on the microphone, but I'm not sure. >> Thanks. Um, I just wanted to ask, is there anything that the spec file library can't do right now? Like specifically like tags it can't edit or limitations that you would like to highlight? >> Uh, not really. The only well not everything is like high level. So sometimes you have to do more work than you than it should be necessary probably. But the only downside I'm aware of is if there are spec files where there are conditions that uh span across or like for example there is else in the middle of a section >> or yeah it because the par is not counting with it and uh there is open issue for that. Thanks. Um hello uh Pavl again. Uh I'm engineer and RPM uh build system developer at Redhead. And in this kind of lightning talk, I'd like to explain you what are my what are my headaches with build systems and designing them and especially source RPM or RPM built systems. Uh a little bit of motivation anyone did before switch to root download some weird uh script from the internet and pipe it to bash to install some important software. Well, I did before only if I really have to install something necessary for my day-to-day job and the people decide not to package these things into Federa, which really makes me like angry. But anyway, anyone uh generated a spec uh source RPM file from a spec file before using either RPM build or fat package source RPM or title source RPM you should be you should be aware that these things are similarly dangerous except that you are not rude but but still um but let me start with probably known things. Uh can anyone tell me what's wrong with this uh with this spec file? What can happen when I try to build it? >> Yeah, exactly. Yeah, there is there is this little typo the dollar sign instead of a person sign meaning that I'm I'm referring to a non-existing a non-existing environment v. So I'm basically trying to remove vir which probably I cannot because I'm not a root but uh if I was I mean how how do you protect against these things you probably don't run as root the builds but you shouldn't do this under your normal normal user like that one that you are using for firefoxing and stuff like that and visiting your internet banking please don't uh and you probably use mock Maybe maybe you don't uh mock tries to I I mean I want to underline that on a best effort basis isolate you from this kind of shooting yourself into food. So here comes source RPMs. Uh can anyone tell me what can happen here when when you try to when you try to build a source RPM from this spec file. I'm not I'm not going to blame you now. You cannot know that. You don't know that because you cannot uh because you don't know what's inside that shell script over there. Uh actually we need to evaluate that one to get the kar uh macro content to get the version to actually place the version in the in the uh s RPM file name. uh hence uh I mean even generating source RPM is not really safe always depending what's inside that script uh and you shouldn't probably like blindly trust the spec files out there how do you protect against these failures mock source RPM doesn't help here of course you need to get the source RPM first so yeah fortunately there's a mock d-spec option which is unfortunately not well known uh but you are here so you're lucky you now know and uh yeah I wanted to point out that mock retries on the best effort to isolate you some some options are not yet well done some are buggy for example this example option uh is still using RPM from host meaning that it it suffers from these issues but let me stop here I am not here to talk about bugs in software that I maintain so quick uh quick mention of Lua. Lua is touring complete as well as the shell script. So it can cause the similar damage to your system if you build untrusted spec files. Um so how this all relates to build system headaches that I have. Uh we basically want to let all of our users build whatever they prefer. Uh they they builds are done on virtual machines. So if they break it, they have the VM broken. We don't care. We just recyclate the the machine and start a new one instead. But we want to allow them to build from GitHub or federalist git and basically cach c the sources. Uh I'll tell you why later. And then on each of the VMs uh build one truth according to users wishes. Why we c it? Uh the reason is that we don't want to redownload the sources all the time from GitHub. We don't want to do distributive attacks to Pegure.io and stuff like that. And how do we cache? Uh uh we basically run another disgracer. Uh and uh we transform the the sources from GitHub using source RPM files to this this proxy this Git. And did I say that I use s RPM files for this? So uh yeah that's not really safe and we need to be careful there while generating those RPM files. And these things are not only about security. Uh some people do weird things like they prefer using different tarbles when building on Fedora and different tarbles elsewhere. I don't know why but uh yeah these kind of things are not yet well solved in in corporate uh at this point in time. If you are curious take a look at this issue. So I was always asking myself whether we can like replace this uh s RPM file which is distribution and arc uh uh specific with a tarable that is arc agnostic and distribution as well. And most of the time we could uh but um [clears throat] yeah we have we have the sources file for example in in this git so which deterministically identifies all the sources that are or at least can be used at RPM build time. So we could basically do git archive from federadis git and append I mean create a master tarable of this archive plus all those sources uh and use that for caching but federa is not making our life easier in this case. Uh we invented a way to not provide change locks at all in Fedora. Uh yeah, this RPM autospec thing um basically means that the git archive is no longer enough at least unless we want to lose the auto I mean the generated change log and the generated uh release field. Hence we need to uh I mean first thing we need to uh do full clones when generating uh generating those RPMs which is not always uh cheap operation and we need to parse the spec file to get those things like version and release to actually have the right values for generating the change log and for that we need to call RPM parser and that's not always safe Right. So another headache is this kind of exclusive arch. Uh I mean build systems don't want to waste potentially expensive S390 VMs just to realize that they cannot be built because there is this exclusive arc thing. So we ideally want to parse the spec file in advance to realize that it doesn't make sense to uh evaluate or to to start the S390 VM. Yeah. So, how do you protect yourself or how should we all protect ourselves? We we should really like be careful. Uh the same way as we don't do or at least don't prefer doing curl and pipe to bash, we shouldn't blindly build uh binary RPMs and not even source RPMs. Uh and we should never build RPMs as root or like some kind of privilege to user user ids. Uh so for real what can we do about this in the future as as the ecosystem? Um I talked about this with the clever and brave people maintaining RPM within redhead and this issue was opened by Panumatan as a result of the discussion. So we could basically have a new new lowprivileged mode in RPM not doing these kind of dangerous things like shell and Lua maybe not doing includes um and that would basically that mode should basically ignore unknown spec file texts those that are too new for that particular version of RPM. right now RPM if it doesn't know the particles tech it bombs and fails and it doesn't parse the spec file at all. Another option maybe uh here comes a little announcement of my Christmas 2024 uh project called I mean work in progress no RPM. It's an complete RPM microprocessor at least at this point in time. It's written in pure Python. So if you if you wanted to parse spec files on nonRPM distros, you have no RPM, you can use basically this one. It could be installed from Pippi if anyone packaged for it. Uh and yeah, here comes a little example how that can work. Uh you basically optionally can load all the macro definitions on your system using the system macro registry and using that database expand a string that should have a spec file loaded. uh I mean that's a spec file as a string and then you can query the database or the registry of of macros this way. Uh to sum it up uh if can if I can have a wish uh please don't uh don't make our headaches worse and keep your spec file as spec spec files as simple as as possible. ideally at least the preamble section that defines the name, version, release, sources, patches and stuff like that because this kind of really matters. Uh for example, that's one example of many uh this kind of short commit uh references. These are using bash for no really good reason. You can use equivalent directly with some macro macro syntax. And if you could do this switch, please do because that really like that really like matters. If we do this kind of switch uh to uh to the new mode of RPM or to no RPM in build systems, uh the variant below will be parsible the the above no. Okay, that's about it. Any questions? So, if I use the no RPM library, uh how big of a chance is it will work for my spec file? It depends what what exactly you want to read. Uh I tested it on the version release. Basically those things that we need to make RPM autospec happy to successfully generate the the change logs and releases. And it was like I tested it on all those uh row height spec files. It's like 24 thousands of spec files and only like 300 of them did not gave me the same value for for release and version. So it's pretty pretty good. But if you wanted to parse other things, I mean there is a huge to-do list in the new RPM library that needs to be implemented to provide better results. So what about generate uh dynamic build requires like being able to evaluate build requires and p down a list to to identify what a build environment needs to be created with ahead of time? >> Of course not. Yeah, you probably know uh for dynamic build requires you need to extract the tarable and run some scripts that are fully on control of upstream basically. So we don't want to evaluate ideally anything to get the version of the of the software from spec file. So so no um is the no RPM packaged? >> It is not yet. As I said, it's just the Christmas idea of this year. So, going to going to make it Fedora soon. So, if I want to protect myself the best, uh how should I build uh random unknown uh specs downloaded from the internet? Uh uh should I do it in a container or something? >> Uh submit it to copper. There are VMs that we dispose. If you get it broken, nobody cares. Uh or I mean you should really review the spec file first. Uh in theory, mock protects you, but it's on a best effort basis. So if you use the mock dspec and you give it the spec file, it is most probably okay. But if the person tries really hard to escape from a mock, it would he would be probably successful. So question for both of you. So how is the spec file package like different from the no RPM? Okay, so that's probably on me. Uh well, spec file uses RPM for micro expansion and uh condition evaluation. Uh there is actually open issue for about not doing this and implementing something like no RPM inside the spec file library. But uh it's just an yeah there is no plan yet. It wouldn't be so easy. I mean well I guess it would be as Pavl said maybe the basic stuff could yeah could be possible in a short time but definitely not uh all the complexities that IPM is capable of. The spec file is really widely used nowadays. Like we use that library for every single built-in copper. So it probably parses all everything you need. But it uses RPM in the background. So you should know that if the spec file is uh dangerous then then you face potential problems. Any other question? Okay, so thanks for attention and enjoy the rest