TeslaGov / ngx-http-auth-jwt-module

Secure your NGINX locations with JWT
MIT License
317 stars 122 forks source link

Is it possible to compile with -fPIE? #46

Closed plastikat closed 6 years ago

plastikat commented 6 years ago

Sorry for a newbie question but I am not too good with compilers. I tried to compile your project on Ubuntu 16.04. To be "binary compatible" the module must be compiled with the same flags, so I've taken these from Ubuntu nginx:

--with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now'

The compilations fails with:

/usr/bin/ld: objs/addon/src/ngx_http_auth_jwt_module.o: relocation R_X86_64_PC32 against undefined symbol `ngx_http_core_module' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value

As far as I figure this is related to those "position-independent executable" flags (-fPIE, -pie) used by Ubuntu. So my question is if it's even possible to compile your module with such flags?

fitzyjoe commented 6 years ago

I have had to use particular versions of NGINX because of my client's requirements. Along the way, as I have changed versions, I have had to change my compiler flags to match the flags that the NGINX binary was compiled with. You can get the list of flags for the binary you are using by executing nginx with the -V option. It gives the compiler flags. You may notice in my project, in the Dockerfile, I have a bunch of commented out ./configure lines that went with different versions of NGINX. Currently, I'm using NGINX 1.12.2 from EPEL7... and because that's newer than 1.11.5, I could probably switch to "--with-compat" That option makes it possible for your module to be used with a different version of NGINX without recompiling.

On Mon, Jul 9, 2018 at 11:08 AM plastikat notifications@github.com wrote:

Sorry for a newbie question but I am not too good with compilers. I tried to compile your project on Ubuntu 16.04. To be "binary compatible" the module must be compiled with the same flags, so I've taken these from Ubuntu nginx:

--with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now'

The compilations fails with:

/usr/bin/ld: objs/addon/src/ngx_http_auth_jwt_module.o: relocation R_X86_64_PC32 against undefined symbol `ngx_http_core_module' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value

As far as I figure this is related to those "position-independent executable" flags (-fPIE, -pie) used by Ubuntu. So my question is if it's even possible to compile your module with such flags?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/TeslaGov/ngx-http-auth-jwt-module/issues/46, or mute the thread https://github.com/notifications/unsubscribe-auth/AF68mvGEJqN-WOGho8O4FE-i4Lo0VARIks5uE3HngaJpZM4VH4Yl .

plastikat commented 6 years ago

Thanks for your reply and the hint about the --with-compat option, I hadn't stumbled across it yet.

Unfortunately, as you mention, it was introduced in 1.11.5. Since I am bound by my client's requirements too (Ubuntu 16.04) this option would not help me since this Ubuntu version is currently shipped with 1.10.3. On top of that this thread explains that it would only work, I quote:

assuming main nginx binary is compiled --with-compat [too]

Just like you, I was getting the compiler flags from nginx -V and the flags I mention in my original question are the flags from Nginx on Ubuntu 16.04 so I am ultimately bound by those flags to compile a compatible module (since to use a distribution binary is a requirement too).

AFAIU the compiler flags -fPIE used in Ubuntu nginx prevents the compilation because, I quote again:

relocation R_X86_64_PC32 against undefined symbol `ngx_http_core_module' can not be used when making a shared object

From my understanding, when using a -fPIE flag is it not possible to use a statically defined symbol (ngx_http_core_module) when making a dynamically loaded library (shared object).

So my main question is if understand the situation correctly?

And the secondary question is if it is at all feasible to adapt your source code to make it compatible with -fPIE or it is practically impossible and this flag used by Ubuntu effectively prevents us to use any dynamic module with their Nginx binary?

fitzyjoe commented 6 years ago

I understand what you are asking, but I don’t know the answer to your question I have found that not all compiler args must be used exactly to have nginx accept binary compatibility. I poked around and it looks like PIC is appropriate for compiling a shared object while PIE is appropriate for an executable. Can you try compiling the module with -fPIC?

Sent from my iPhone

On Jul 12, 2018, at 11:32 PM, plastikat notifications@github.com wrote:

Thanks for your reply and the hint about the --with-compat option, I hadn't stumbled across it yet.

Unfortunately, as you mention, it was introduced in 1.11.5. Since I am bound by my client's requirements too (Ubuntu 16.04) this option would not help me since this Ubuntu version is currently shipped with 1.10.3. On top of that this thread explains that it would only work, I quote:

assuming main nginx binary is compiled --with-compat [too]

Just like you, I was getting the compiler flags from nginx -V and the flags I mention in my original question are the flags from Nginx on Ubuntu 16.04 so I am ultimately bound by those flags to compile a compatible module.

AFAIU the compiler flags -fPIE used in Ubuntu nginx prevents the compilation because, I quote again:

relocation R_X86_64_PC32 against undefined symbol `ngx_http_core_module' can not be used when making a shared object

From my understanding, when using a -fPIE flag is it not possible to use a statically defined symbol (ngx_http_core_module) when making a dynamically loaded library (shared object).

So my main question is if understand the situation correctly?

And the secondary question is if it is at all feasible to adapt your source code to make it compatible with -fPIE or it is practically impossible and this flag used by Ubuntu effectively prevents us to use any dynamic module with their Nginx binary?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

plastikat commented 6 years ago

Actually I tried compiling with -fPIC specified for both compiler and linker before posting the question here. The compilation process succeeds in this case but Ubuntu Nginx still refuses the module as binary incompatible so I had decided it was a wrong way to go.

I have found that not all compiler args must be used exactly to have nginx accept binary compatibility

This is quite interesting, thanks again for another tip. What I did not remove was that -pie linker flag (given adjacent to -fPIE). I will try to experiment again while playing with arguments.

plastikat commented 6 years ago

I would like to let you know that I eventually managed to compile a "binary compatible" module. I put it in quotation marks on purpose because it turned out it is an Nginx term after all. At first I had an impression it was a general term - that's why I tried hard to keep all the compiler/linker flags.

First I took all the configuration options from nginx -V, then just replaced -fPIE with -fPIC and added --add-dynamic-module=../ngx-http-auth-jwt-module. That's all that was needed indeed.

I failed to get a "binary compatible" module during my previous attempts because I tried to keep the compiler/linker flags, but thought that other options (like all those --with-http_* directives) were not very important, hence I omitted some of them (not to bother with installing their build dependencies). As practice reveals it is the opposite: the compiler/linker flags may be altered to some degree, but all the Nginx directives must be kept exactly the same. Omitting just one option results in a "binary incompatible" module.

Also I would like say big thanks to the author for this module because there are really not much other options for the mainline Nginx (I mean free and without those Lua mods). You're doing a good job!