]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: mworker/cli: fix user and operator permission via @@<pid> in master CLI
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 4 May 2026 16:35:46 +0000 (18:35 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Mon, 4 May 2026 17:03:48 +0000 (19:03 +0200)
When @@<pid> is matched in pcli_parse_request(), no "operator -" or
"user -" is being sent before the command, like it's done for @<pid>.

It leads to privileges not being respected and commands are sent as
admin.

Fix this by applying the access-level downgrade in the @@<pid> path,
like it's done for @<pid>.

Must be backported to 3.2.

Reported-by: Omkhar Arasaratnam <omkhar@linkedin.com>
src/cli.c

index 0c327dd03f09d364104f241bf907dcc8da19b5ca..62158f2d6fbae01bb4f996d2add21484d82d17c8 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -3269,8 +3269,34 @@ int pcli_parse_request(struct stream *s, struct channel *req, char **errmsg, int
        if (!(pcli->flags & PCLI_F_PAYLOAD)) {
                /* look for the '@@' prefix and intercept it if found */
                ret = pcli_find_bidir_prefix(s, req, &p, end, errmsg, next_pid);
-               if (ret != 0) // success or failure
+               if (ret < 0) /* error */
                        goto end;
+               if (ret > 0) {
+                       /* @@<pid> matched: apply access-level downgrade before
+                        * forwarding to the worker. The worker sockpair listener
+                        * defaults to ACCESS_LVL_ADMIN, so without this a
+                        * user/operator-level master-CLI client would inherit
+                        * admin rights on the worker side.
+                        */
+                       if (pcli_has_level(s, ACCESS_LVL_ADMIN)) {
+                               /* admin already, no downgrade needed */
+                       } else if (pcli_has_level(s, ACCESS_LVL_OPER)) {
+                               const char *cmd = "operator -;";
+                               if (!ci_insert(req, 0, cmd, strlen(cmd))) {
+                                       ret = -1;
+                                       goto end;
+                               }
+                               ret += strlen(cmd);
+                       } else if (pcli_has_level(s, ACCESS_LVL_USER)) {
+                               const char *cmd = "user -;";
+                               if (!ci_insert(req, 0, cmd, strlen(cmd))) {
+                                       ret = -1;
+                                       goto end;
+                               }
+                               ret += strlen(cmd);
+                       }
+                       goto end;
+               }
 
                reql = p - str;
                p = str;