nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.36k stars 322 forks source link

Caused segfault happened in nxt_conf_op_compile(). #365

Open hongzhidao opened 4 years ago

hongzhidao commented 4 years ago

Hi.

The following operations can cause fegfault.

# conf.json
{
    "listeners": {
        "*:8080": {
            "pass":"routes"
        }

    },

    "routes": [
        {
            "match": {
                "uri": "/"
            },

            "action": {
                "share":"/tmp/html"
            }
        }
    ]
}
curl -X PUT -d '"/"' http://127.1:8000/config/routes/0/match/uri/0
curl -X PUT -d '"/"' http://127.1:8000/config/routes/0/match/uri/a

Here's the patch. Take a look, please.

# HG changeset patch
# User hongzhidao <hongzhidao@gmail.com>
# Date 1577705904 -28800
# Node ID 1fcb5fba6ab659cd1f4be71b87b567c7b6769360
# Parent  96e6ac1926f86faf542cf380a8d2eadebd3eac5b
Fixed segfault happened in nxt_conf_op_compile().

diff -r 96e6ac1926f8 -r 1fcb5fba6ab6 src/nxt_conf.c
--- a/src/nxt_conf.c    Thu Dec 26 17:04:37 2019 +0300
+++ b/src/nxt_conf.c    Mon Dec 30 19:38:24 2019 +0800
@@ -814,6 +814,10 @@

         default:
             node = NULL;
+
+            if (parse.last) {
+                return NXT_CONF_OP_NOT_FOUND;
+            }
         }

         if (parse.last) {

BTW, how to run UNIT tests beside make tests?

i4ki commented 4 years ago

Hi @hongzhidao

Thanks for the report and patch.

About the "how to run unit tests":

$ ./configure <parameters as usual>
$ ./configure python
$ ./configure php
$ ./configure perl
...
# some languages require specific config
$ GOPATH=`pwd`/build/go ./configure go
...

Then, run the tests with:

$ ./test/run.py

Or you can run specific test files with:

$ python3 ./test/test_python_application.py

Or even specific python test methods:

$ python3 ./test/test_python_application.py -f <name of the test method>

Take a look in the helper passing -h, you can get detailed debug mode for http traffic also.

Hope it helps, sorry for the late reply.

hongzhidao commented 4 years ago

@tiago4orion

There are some questions about how to test I still can't understand.

  1. What user should we run? root?
  2. Where should I put the source dir?
  3. Should I run make install first? If yes, I think I need to add --prefix while configure.

Now, I got unexpected messages on the follow way. In /root/unit/ with root user.

$ ./configure
$ ./configure python
$ make

python3 ./test/test_routing.py
2020/02/25 05:04:30 [info] 57755#57755 unit started
Unit has no python module(s)
s
----------------------------------------------------------------------
Ran 0 tests in 0.212s

OK (skipped=1)

/tmp/unit-test-33sfj2j9/unit.log

2020/02/25 05:07:11 [info] 57833#57833 unit started
2020/02/25 05:07:11 [info] 57834#57834 discovery started
2020/02/25 05:07:11 [notice] 57834#57834 no modules matching: "/root/unit/build/*.unit.so" found
2020/02/25 05:07:11 [notice] 57833#57833 process 57834 exited with code 0
2020/02/25 05:07:11 [info] 57836#57836 router started
2020/02/25 05:07:11 [info] 57835#57835 controller started

I checked the source code. Permission denied happens in ret = glob(path, 0, NULL, &glb);.

How can I do it in the right way, can you show an example? Thanks.

i4ki commented 4 years ago

Hi @hongzhidao

The core workers (discovery, controller and router) run with unprivileged user by default, then they need access to the modules directory (build in case of tests). The tests are self-contained (they don't look to the prefix directory, doesn't matter if you set it or not).

Have a look here: https://github.com/nginx/unit/blob/master/test/unit/main.py#L215

If you run everything with an unprivileged user, it works fine:

$ cd /tmp
$ hg clone ...
$ ./configure
$ ./configure python
$ ls build
Makefile  autoconf.data  autoconf.err  echo  nxt_auto_config.h  src
$ make
...
$ ls build/
Makefile  autoconf.data  autoconf.err  echo  libnxt.a  nxt_auto_config.h  nxt_version.h 
*python.unit.so*  src  unitd
$ ./test/run.py # or like you did: python3 test/test_routing.py

2020/02/25 10:28:38 [warn] 18453#18453 Unit is running unprivileged, then it cannot use arbitrary user and group.
2020/02/25 10:28:38 [info] 18453#18453 unit started
test_access_log_change (test_access_log.TestAccessLog) ... 
2020/02/25 10:28:38 [warn] 18459#18459 Unit is running unprivileged, then it cannot use arbitrary user and group.
2020/02/25 10:28:38 [info] 18459#18459 unit started
ok
...
...

----------------------------------------------------------------------
Ran 264 tests in 146.674s

OK (skipped=35)

Python, PHP, Java, and Perl doesn't require anything special to run the tests. For example, for Go, you need to call configure setting GOPATH to the build directory:

GOPATH=`pwd`/build/go ./configure go

If you want to run as root, it works but you need to make sure the build directory is readable by other users. I just test in ubuntu, doing everything as root and it works, maybe you can check your umask setting or just call configure and make first with an unprivileged user and then run the tests as root. Most of the tests don't need root.

Let me know if it works for you, if not please say more about your environment (operating system, and so on).

hongzhidao commented 4 years ago

@tiago4orion It works well form me, thanks again :)