Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uKeKD-008Sbb-NS for pgsql-hackers@arkaria.postgresql.org; Thu, 29 May 2025 14:33:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uKeKC-009V7L-Dl for pgsql-hackers@arkaria.postgresql.org; Thu, 29 May 2025 14:33:40 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uKeKC-009V7D-1e for pgsql-hackers@lists.postgresql.org; Thu, 29 May 2025 14:33:40 +0000 Received: from mail-il1-x135.google.com ([2607:f8b0:4864:20::135]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uKeK8-000jRR-2T for pgsql-hackers@lists.postgresql.org; Thu, 29 May 2025 14:33:39 +0000 Received: by mail-il1-x135.google.com with SMTP id e9e14a558f8ab-3dd81f9ce2eso3170645ab.1 for ; Thu, 29 May 2025 07:33:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1748529215; x=1749134015; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=EHqcC30huIDXt5dS0aKUkF4QXUZj3gkDLxlhiVVQ7FQ=; b=k9Ka53lWoxrx6CPZbs0brWN5nIXgUiS5ZL6rzvW/ol238CjOvMwhXV+ksLY6nAW/Jf Nxe0ly5Q1B9jURGIrmTCTA9Vp/85LDa2ch2xJE9WhWwrb182iFHSpUs8dUwJi1f55TH/ EdG6Dh1yseDLkQdaPHl+LZUIsZfw4HjCDLT6/YdudlTLE4mnRFhduzBNzbln2zdrTE5m L0zvWaB3h+o1/mCcHmFhpE7oDnoGuPXXgop+aJJKhdLJ45fDkii9frMpZXGSNmVDTjTo kRu1NYBLRAF8sTU6m8kMf1y7bNPZHvStg3sxUhenOJtSA0wjJYgoSuqOMdr4foxECMp+ RQ9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1748529215; x=1749134015; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=EHqcC30huIDXt5dS0aKUkF4QXUZj3gkDLxlhiVVQ7FQ=; b=gnWpfNPMXSl86SvR4yp076H1rmQ09HfNeMNpmJ2nAwW/SzMmMGWknVnaK8L7EpxQmq FQ1UYF7LZRCGzhzmOW4KaUtyKcER5v3rE1wWc5NxaPGpzFzPjtwJ77AlbW4XfNzUiD4W W7825UUgcDQE28eBi18GAQrIB0ICy0qZkMeprD9nHRG7bjGdnquJ7rX4W78iPUoIiVWz 0WzwNFfCWmVUFuXUU82CLHD5BKaB12BAA4qgbcWAUG3teZFTYw4FvqfvOQ57IFtRIYya f7+nrSD47Fn7EJZB8tanDS8ycRTAWO+17r7yY9oUzc09iMwdSI+2NhsuQQjpM6PjKAIz dwxg== X-Gm-Message-State: AOJu0YwZyO2ZCEogzgznu50ie1qHnyHwDi11rH+vZ4I4kjsg6/VjTTB8 Pv9SMktGFy3GfPPdvs/odnW/H8jHXJYBZhyXLYuwDUpTdxKE8hTQojcrHGnC1Zvq0GEi0k+HMfe gK4nk2Xb0nEyk5kwr6qLhZnPv6LmImkDT1iEu X-Gm-Gg: ASbGncvbO7WTdYcuy6CeC0uIG7c+uAnmEFqAdIz34yW4u3a/8JYrqCpLYElmseuDn04 u/4tlfzaGm4q5o9b1fhPLa/WEcUsOuZ5hDPKpinxm1K03X1Rg3j9HlYI+quaAVG/lQG2/crDd4a 3ivxiwVtfkpzHJyasdY+qEKCrJWifuSS6/WiCyNWg38WJeiKMJjbU8bjONI4pFR0XUiXaVBbeZ6 PCYDg== X-Google-Smtp-Source: AGHT+IGg86vvRwQfEhJcCWwR1KmXDihgiIl7qu4QTTiD+e+VMEdNHAQeYdwH8pUM1i1d6mj4HF8R8ekDJvlmPjjQCNw= X-Received: by 2002:a05:6e02:19c9:b0:3dc:7fa4:847 with SMTP id e9e14a558f8ab-3dd90ca2e28mr44065695ab.9.1748529214697; Thu, 29 May 2025 07:33:34 -0700 (PDT) MIME-Version: 1.0 From: Greg Sabino Mullane Date: Thu, 29 May 2025 10:32:57 -0400 X-Gm-Features: AX0GCFv6Cv6TrZaa9NZRFL1kAu5K_KeK8-56sfeeI2r8fEt5hrrqj9KITE0gXT8 Message-ID: Subject: POC: Carefully exposing information without authentication To: "pgsql-hackers@lists.postgresql.org" Content-Type: multipart/mixed; boundary="000000000000b8deee0636472ea7" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000b8deee0636472ea7 Content-Type: multipart/alternative; boundary="000000000000b8deec0636472ea5" --000000000000b8deec0636472ea5 Content-Type: text/plain; charset="UTF-8" Proposal: Allow a carefully curated selection of information to be shown without authentication. A common task for an HA system or a load balancer is to quickly determine which of your Postgres clusters is the primary, and which are the replicas. The canonical way to do this is to log in to each server with a valid username and password, and then run pg_is_in_recovery(). That's a lot of work to determine if a server is a replica or not, and it struck me that this true/false information about a running cluster is not super-sensitive information. In other words, would it really be wrong if there was a way to advertise that information without having to log in? I toyed with the idea of Postgres maintaining some sort of signal file, but then I realized that we already have a process, listening on a known port, that has that information available to us. Thus, this POC (proof of concept), which lets the postmaster scan for incoming requests and quickly handle them *before* doing forking and authenticating. We scan for a simple trigger string, and immediately return the information to the client. It also occured to me that since we are going to need to provide a non-Postgres-protocol special trigger string, and we might as well do something like "GET /info" to allow existing programs to treat Postgres as a mini http server. To that end, we end up with something like this: $ psql -p 5432 -tc 'select pg_is_in_recovery()' t $ curl http://localhost:5432/foobar curl: (52) Empty reply from server $ curl http://localhost:5432/info RECOVERY: 1 To accomplish this, we have boolean GUC flags (defaulting to false) that control which information is exposed. For the example above, the expose_recovery boolean has been set to true. If any of these GUCs are true, we take a slight detour right after we accept() but before we actually fork. We use recv with the MSG_PEEK flag to take a quick scan of the incoming data, and use strncmp to see if it matches. If it does, we send() some information and move on without forking. If it doesn't, we simply move on as if we were never there, and proceed to the next step of forking a new backend to start the authentication process. There are three pieces of information that can be exposed with this patch. There may be more in the future, but these are all simple, global, and not (IMO) security leaks. The GUCs are expose_recovery, expose_sysid, and expose_version. Each one adds a line to the output in a KEY: VALUE format for the GET /info endpoint. The raw value is output for the direct endpoints: * GET /replica * GET /sysid * GET /version The expose_recovery GUC uses RecoveryInProgress() to return a 1 or a 0. This is returned by the GET /replica endpoint. The expose_sysid GUC returns GetSystemIdentifier(). Since this can be thought of as a fingerprint for the server, it's a nice way for external programs to determine if the cluster is the same one it saw last time, or for leader/replica matching. The purpose of the expose_version GUC is to output PG_VERSION_NUM. This will allow external tools - particularly security scanners - to know the exact version of Postgres that is running. While some may consider this privileged information, tools are already taking advantage of our debug loophole to make an educated guess about the version. See my old post about this: https://www.endpointdev.com/blog/2010/05/finding-postgresql-version-without/ Note that this guess by security scanners is sometimes wrong, or only able to cover a range of versions. Thus, we should give them the correct answer, rather than providing a dubious one via some trickery. Here's some example output with all three enabled: $ psql -c 'alter system set expose_recovery=on' $ psql -c 'alter system set expose_version=on' $ psql -c 'alter system set expose_sysid=on' $ psql -c 'select pg_reload_conf()' $ curl http://localhost:5432/version 180000 $ curl http://localhost:5432/info RECOVERY: 1 SYSID: 7504513530771111839 VERSION: 180000 But wait! We can do more. For the recovery, we don't even need a string that spells out "RECOVERY:", we only need to know if the server is in recovery or not. In short, a boolean. Patroni does this in its API with a call of HEAD /replica. It returns a different HTTP code if the server is a replica (200) or not a replica (503). We can do the same thing! What's more, we can do it in a way that will allow existing calls to simply point to the postgres server instead of a Patroni process, and get the same result back, but faster. Here's an example of what that looks like: ## Calling Patroni $ curl -s -w "%{http_code}" -o /dev/null -I http://localhost:8008/replica 200 ## Calling Postgres directly $ curl -s -w "%{http_code}" -o /dev/null -I http://localhost:5432/replica 200 Here's a simple Python program showing how easy it is to grab this information: import socket try: with socket.create_connection(('localhost', 5432), timeout=1) as s: s.sendall(b'GET /sysid') print(s.recv(200).split(b'\r\n\r\n',1)[1].decode()) except Exception as e: print(f"Error: {e}") That's the basic idea: proof of concept patch is attached. Additional things to do: * handling socket quirks (esp. Win32) * docs (once details are hashed out) * moving things around (everything is in one function right now for reading ease) Cheers, Greg -- Crunchy Data - https://www.crunchydata.com Enterprise Postgres Software Products & Tech Support --000000000000b8deec0636472ea5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Proposal: Allow a carefully curated selection of= information to be shown without authentication.

A common task for a= n HA system or a load balancer is to quickly determine which of your Postgr= es clusters is the primary, and which are the replicas. The canonical way t= o do this is to log in to each server with a valid username and password, a= nd then run pg_is_in_recovery().
That's a lot of work to determine i= f a server is a replica or not, and it struck me that this true/false infor= mation about a running cluster is not super-sensitive information. In other= words, would it really be wrong if there was a way to advertise that infor= mation without having to log in? I toyed with the idea of Postgres maintain= ing some sort of signal file, but then I realized that we already have a pr= ocess, listening on a known port, that has that information available to us= .

Thus, this POC (proof of concept), which lets the postmaster scan = for incoming requests and quickly handle them *before* doing forking and au= thenticating. We scan for a simple trigger string, and immediately return t= he information to the client.

It also occured to me that since we ar= e going to need to provide a non-Postgres-protocol special trigger string, = and we might as well do something like "GET /info" to allow exist= ing programs to treat Postgres as a mini http server. To that end, we endup with something like this:

$ psql -p 5432 -tc 'select pg_is_= in_recovery()'
t

$ curl=C2=A0http://localhost:5432/foobar
curl: (52) E= mpty reply from server

$ curl=C2=A0http://localhost:5432/info
RECOVERY: 1
To accomplish this, we have boolean GUC flags (defaulting to false) that = control which information is exposed. For the example above, the expose_rec= overy boolean has been set to true. If any of these GUCs are true, we take = a slight detour right after we accept() but before we actually fork. We use= recv with the MSG_PEEK flag to take a quick scan of the incoming data, and= use strncmp to see if it matches. If it does, we send() some information a= nd move on without forking. If it doesn't, we simply move on as if we w= ere never there, and proceed to the next step of forking a new backend to s= tart the authentication process.

There are three pieces of informati= on that can be exposed with this patch. There may be more in the future, bu= t these are all simple, global, and not (IMO) security leaks. The GUCs are = expose_recovery, expose_sysid, and expose_version. Each one adds a line to = the output in a KEY: VALUE format for the GET /info endpoint. The raw value= is output for the direct endpoints:

* GET /replica
* = GET /sysid
* GET /version

The expose_recovery GUC uses RecoveryIn= Progress() to return a 1 or a 0. This is returned by the GET /replica endpo= int.

The expose_sysid GUC returns GetSystemIdentifier(). Since this = can be thought of as a fingerprint for the server, it's a nice way for = external programs to determine if the cluster is the same one it saw last t= ime, or for leader/replica matching.

The purpose of the expose_versi= on GUC is to output PG_VERSION_NUM. This will allow external tools - partic= ularly security scanners - to know the exact version of Postgres that is ru= nning. While some may consider this privileged information, tools are alrea= dy taking advantage of our debug loophole to make an educated guess about t= he version. See my old post about this:
= https://www.endpointdev.com/blog/2010/05/finding-postgresql-version-without= /
Note that this guess by security scanners is sometimes wrong, or o= nly able to cover a range of versions. Thus, we should give them the correc= t answer, rather than providing a dubious one via some trickery.

Her= e's some example output with all three enabled:

$ psql -c 'a= lter system set expose_recovery=3Don'
$ psql -c 'alter system se= t expose_version=3Don'
$ psql -c 'alter system set expose_sysid= =3Don'
$ psql -c 'select pg_reload_conf()'

$ curl=C2= =A0http://local= host:5432/version
180000

$ curl=C2=A0http://localhost:5432/info
RECOVERY= : 1
SYSID: 7504513530771111839
VERSION: 180000

But wait! We ca= n do more. For the recovery, we don't even need a string that spells ou= t "RECOVERY:", we only need to know if the server is in recovery = or not. In short, a boolean. Patroni does this in its API with a call of HE= AD /replica. It returns a different HTTP code if the server is a replica (2= 00) or not a replica (503). We can do the same thing! What's more, we c= an do it in a way that will allow existing calls to simply point to the pos= tgres server instead of a Patroni process, and get the same result back, bu= t faster. Here's an example of what that looks like:

## Calling = Patroni
$ curl -s -w "%{http_code}" -o /dev/null -I=C2=A0http://localhost:800= 8/replica
200

## Calling Postgres directly
$ curl -s -w &q= uot;%{http_code}" -o /dev/null -I=C2=A0http://localhost:5432/replica
200
Here's a simple Python program showing how easy it is to grab this in= formation:

import socket

try:
=C2=A0 with socket.create_co= nnection(('localhost', 5432), timeout=3D1) as s:
=C2=A0 =C2=A0 s= .sendall(b'GET /sysid')
=C2=A0 =C2=A0 print(s.recv(200).split(b&= #39;\r\n\r\n',1)[1].decode())
except Exception as e:
=C2=A0 print= (f"Error: {e}")


That's the basic idea: proof of co= ncept patch is attached. Additional things to do:

* handling socket = quirks (esp. Win32)
* docs (once details are hashed out)
* moving thi= ngs around (everything is in one function right now for reading ease)
Cheers,
Greg

--=
Enterprise Postgres Soft= ware Products & Tech Support

--000000000000b8deec0636472ea5-- --000000000000b8deee0636472ea7 Content-Type: application/octet-stream; name="0001-Allow-specific-information-to-be-output-directly-by-Postgres.patch" Content-Disposition: attachment; filename="0001-Allow-specific-information-to-be-output-directly-by-Postgres.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_mb9h2fvv0 RnJvbSBmZDU4NjEyZjc0YTMwOGFlZDNmMGQzY2FmNzkyNTBjMGJmY2UyMDY4IE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBHcmVnIFNhYmlubyBNdWxsYW5lIDxncmVnQHR1cm5zdGVwLmNv bT4KRGF0ZTogVHVlLCAyNyBNYXkgMjAyNSAwNzozMDowNyAtMDQwMApTdWJqZWN0OiBbUEFUQ0hd IEFsbG93IHNwZWNpZmljIGluZm9ybWF0aW9uIHRvIGJlIG91dHB1dCBkaXJlY3RseSBieSBQb3N0 Z3Jlcy4KCi0tLQogc3JjL2JhY2tlbmQvcG9zdG1hc3Rlci9wb3N0bWFzdGVyLmMgICAgICAgICAg IHwgMTk2ICsrKysrKysrKysrKysrKysrLQogc3JjL2JhY2tlbmQvdXRpbHMvbWlzYy9ndWNfdGFi bGVzLmMgICAgICAgICAgIHwgIDI3ICsrKwogc3JjL2JhY2tlbmQvdXRpbHMvbWlzYy9wb3N0Z3Jl c3FsLmNvbmYuc2FtcGxlIHwgICA4ICsKIHNyYy9pbmNsdWRlL3Bvc3RtYXN0ZXIvcG9zdG1hc3Rl ci5oICAgICAgICAgICB8ICAgNCArCiBzcmMvdGVzdC9wb3N0bWFzdGVyL3QvMDA0X2V4cG9zZWQu cGwgICAgICAgICAgfCAxMDUgKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCAzMzkgaW5zZXJ0 aW9ucygrKSwgMSBkZWxldGlvbigtKQogY3JlYXRlIG1vZGUgMTAwNjQ0IHNyYy90ZXN0L3Bvc3Rt YXN0ZXIvdC8wMDRfZXhwb3NlZC5wbAoKZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL3Bvc3RtYXN0 ZXIvcG9zdG1hc3Rlci5jIGIvc3JjL2JhY2tlbmQvcG9zdG1hc3Rlci9wb3N0bWFzdGVyLmMKaW5k ZXggNDkwZjdjZS4uNTgxOGY2MyAxMDA2NDQKLS0tIGEvc3JjL2JhY2tlbmQvcG9zdG1hc3Rlci9w b3N0bWFzdGVyLmMKKysrIGIvc3JjL2JhY2tlbmQvcG9zdG1hc3Rlci9wb3N0bWFzdGVyLmMKQEAg LTkyLDYgKzkyLDcgQEAKICNpbmNsdWRlICJhY2Nlc3MveGxvZy5oIgogI2luY2x1ZGUgImFjY2Vz cy94bG9nX2ludGVybmFsLmgiCiAjaW5jbHVkZSAiYWNjZXNzL3hsb2dyZWNvdmVyeS5oIgorI2lu Y2x1ZGUgImFjY2Vzcy94bG9ndXRpbHMuaCIKICNpbmNsdWRlICJjb21tb24vZmlsZV9wZXJtLmgi CiAjaW5jbHVkZSAiY29tbW9uL3BnX3BybmcuaCIKICNpbmNsdWRlICJsaWIvaWxpc3QuaCIKQEAg LTE5Nyw2ICsxOTgsOSBAQCBidG1hc2tfY29udGFpbnMoQmFja2VuZFR5cGVNYXNrIG1hc2ssIEJh Y2tlbmRUeXBlIHQpCiB9CiAKIAoraW50CQkJdG90YWxfZXhwb3NlID0gMDsKKworCiBCYWNrZ3Jv dW5kV29ya2VyICpNeUJnd29ya2VyRW50cnkgPSBOVUxMOwogCiAvKiBUaGUgc29ja2V0IG51bWJl ciB3ZSBhcmUgbGlzdGVuaW5nIGZvciBjb25uZWN0aW9ucyBvbiAqLwpAQCAtMjQ3LDYgKzI1MSwx MCBAQCBjaGFyCSAgICpib25qb3VyX25hbWU7CiBib29sCQlyZXN0YXJ0X2FmdGVyX2NyYXNoID0g dHJ1ZTsKIGJvb2wJCXJlbW92ZV90ZW1wX2ZpbGVzX2FmdGVyX2NyYXNoID0gdHJ1ZTsKIAorYm9v bAkJZXhwb3NlX3JlY292ZXJ5ID0gZmFsc2U7Citib29sCQlleHBvc2Vfc3lzaWQgPSBmYWxzZTsK K2Jvb2wJCWV4cG9zZV92ZXJzaW9uID0gZmFsc2U7CisKIC8qCiAgKiBXaGVuIHRlcm1pbmF0aW5n IGNoaWxkIHByb2Nlc3NlcyBhZnRlciBmYXRhbCBlcnJvcnMsIGxpa2UgYSBjcmFzaCBvZiBhCiAg KiBjaGlsZCBwcm9jZXNzLCB3ZSBub3JtYWxseSBzZW5kIFNJR1FVSVQgLS0gYW5kIG1vc3Qgb3Ro ZXIgY29tbWVudHMgaW4gdGhpcwpAQCAtNDUzLDYgKzQ2MSw4IEBAIHN0YXRpYyB2b2lkIFN0YXJ0 U3lzTG9nZ2VyKHZvaWQpOwogc3RhdGljIHZvaWQgU3RhcnRBdXRvdmFjdXVtV29ya2VyKHZvaWQp Owogc3RhdGljIGJvb2wgU3RhcnRCYWNrZ3JvdW5kV29ya2VyKFJlZ2lzdGVyZWRCZ1dvcmtlciAq cncpOwogc3RhdGljIHZvaWQgSW5pdFBvc3RtYXN0ZXJEZWF0aFdhdGNoSGFuZGxlKHZvaWQpOwor c3RhdGljIGJvb2wgRXhwb3NlSW5mb3JtYXRpb24oaW50IGZkKTsKKwogCiAjaWZkZWYgV0lOMzIK ICNkZWZpbmUgV05PSEFORyAwCQkJCS8qIGlnbm9yZWQsIHNvIGFueSBpbnRlZ2VyIHZhbHVlIHdp bGwgZG8gKi8KQEAgLTE2OTksNyArMTcwOSwxMyBAQCBTZXJ2ZXJMb29wKHZvaWQpCiAJCQkJQ2xp ZW50U29ja2V0IHM7CiAKIAkJCQlpZiAoQWNjZXB0Q29ubmVjdGlvbihldmVudHNbaV0uZmQsICZz KSA9PSBTVEFUVVNfT0spCi0JCQkJCUJhY2tlbmRTdGFydHVwKCZzKTsKKwkJCQl7CisJCQkJCWlm ICgoZXhwb3NlX3JlY292ZXJ5IHx8IGV4cG9zZV9zeXNpZCB8fCBleHBvc2VfdmVyc2lvbikKKwkJ CQkJCSYmIEV4cG9zZUluZm9ybWF0aW9uKHMuc29jaykpCisJCQkJCQl0b3RhbF9leHBvc2UrKzsK KwkJCQkJZWxzZQorCQkJCQkJQmFja2VuZFN0YXJ0dXAoJnMpOworCQkJCX0KIAogCQkJCS8qIFdl IG5vIGxvbmdlciBuZWVkIHRoZSBvcGVuIHNvY2tldCBpbiB0aGlzIHByb2Nlc3MgKi8KIAkJCQlp ZiAocy5zb2NrICE9IFBHSU5WQUxJRF9TT0NLRVQpCkBAIC00NjE2LDMgKzQ2MzIsMTgxIEBAIElu aXRQb3N0bWFzdGVyRGVhdGhXYXRjaEhhbmRsZSh2b2lkKQogCQkJCQkJCQkgR2V0TGFzdEVycm9y KCkpKSk7CiAjZW5kaWYJCQkJCQkJLyogV0lOMzIgKi8KIH0KKworCitzdGF0aWMKK2Jvb2wKK0V4 cG9zZUluZm9ybWF0aW9uKGludCBmZCkKK3sKKworLyoKKyAqIEV4cG9zZUluZm9ybWF0aW9uCisg KgorICoKKyAqIEhhbmRsZSBlYXJseSBzb2NrZXQgcHJvYmUgYmVmb3JlIGZ1bGwgYmFja2VuZCBz dGFydHVwLgorICogUmVzcG9uZHMgdG8gc21hbGwgc2V0IG9mIHByZWRlZmluZWQgZW5kcG9pbnRz IChlLmcuIEdFVCAvaW5mbykKKyAqCisgKiBSZXF1aXJlcyBhdCBsZWFzdCBvbmUgImV4cG9zZV8i IEdVQyB0byBiZSB0cnVlLgorICoKKyAqIFJldHVybnMgdHJ1ZSBpZiBlbmRwb2ludCBpcyByZWNv Z25pemVkLgorICogQ2FsbGVyIGlzIHJlc3BvbnNpYmxlIGZvciBjbG9zaW5nIHRoZSBzb2NrZXQu CisgKi8KKworI2RlZmluZSBFWFBPU0VfTUlOX1FVRVJZIDkJCS8qIFNob3J0ZXN0IHBvc3NpYmxl IGxpbmU6ICJHZXQgL2luZm8iICovCisjZGVmaW5lIEVYUE9TRV9NQVhfUVVFUlkgMTYJCS8qIExv bmdlc3QgcG9zc2libGUgR0VUIGxpbmUgKi8KKworLyogV2hhdCBpbmZvcm1hdGlvbiBpcyBiZWlu ZyByZXR1cm5lZCAqLworCXR5cGVkZWYgZW51bQorCXsKKwkJRVhQT1NFX05PVEhJTkcsCisJCUVY UE9TRV9IRUFEX1JFUExJQ0EsCisJCUVYUE9TRV9HRVRfQUxMLAorCQlFWFBPU0VfR0VUX1JFUExJ Q0EsCisJCUVYUE9TRV9HRVRfU1lTSUQsCisJCUVYUE9TRV9HRVRfVkVSU0lPTiwKKwl9CQkJUmV0 dXJuVHlwZTsKKworCXR5cGVkZWYgc3RydWN0CisJeworCQljb25zdCBjaGFyICplbmRwb2ludDsK KwkJY29uc3QgYm9vbCAqcmVxdWlyZTsKKwkJUmV0dXJuVHlwZQl0eXBlOworCX0JCQllbmRwb2lu dF9hY3Rpb247CisKKwlzdGF0aWMgZW5kcG9pbnRfYWN0aW9uIGVuZHBvaW50X2FjdGlvbnNbXSA9 CisJeworCQl7CisJCQkiSEVBRCAvcmVwbGljYSIsICZleHBvc2VfcmVjb3ZlcnksIEVYUE9TRV9I RUFEX1JFUExJQ0EKKwkJfSwKKwkJeworCQkJIkdFVCAvcmVwbGljYSIsICZleHBvc2VfcmVjb3Zl cnksIEVYUE9TRV9HRVRfUkVQTElDQQorCQl9LAorCQl7CisJCQkiR0VUIC9zeXNpZCIsICZleHBv c2Vfc3lzaWQsIEVYUE9TRV9HRVRfU1lTSUQKKwkJfSwKKwkJeworCQkJIkdFVCAvdmVyc2lvbiIs ICZleHBvc2VfdmVyc2lvbiwgRVhQT1NFX0dFVF9WRVJTSU9OCisJCX0sCisJCXsKKwkJCSJHRVQg L2luZm8iLCBOVUxMLCBFWFBPU0VfR0VUX0FMTAorCQl9CisJfTsKKworCXNzaXplX3QJCW47CisJ Y2hhcgkJYnVmW0VYUE9TRV9NQVhfUVVFUlkgKyAxXTsKKwlpbnQJCQl0eXBlOworCisJQXNzZXJ0 KGV4cG9zZV9yZWNvdmVyeSB8fCBleHBvc2Vfc3lzaWQgfHwgZXhwb3NlX3ZlcnNpb24pOworCisJ ZG8KKwl7CisJCW4gPSByZWN2KGZkLCBidWYsIEVYUE9TRV9NQVhfUVVFUlksIE1TR19QRUVLKTsK Kwl9IHdoaWxlIChuIDwgMCAmJiBlcnJubyA9PSBFSU5UUik7CisKKwkvKgorCSAqIExlYXZlIGFz IHNvb24gYXMgcG9zc2libGUgaWYgbm90IGNoYW5jZSB3ZSBhcmUgaW50ZXJlc3RlZC4gV2UgYWxz bworCSAqIHNpbXBseSByZXR1cm4gZmFsc2UgZm9yIG4gPT0gLTEKKwkgKi8KKwlpZiAobiA8IEVY UE9TRV9NSU5fUVVFUlkpCisJCXJldHVybiBmYWxzZTsKKworCWJ1ZltuXSA9ICdcMCc7CisKKwl0 eXBlID0gRVhQT1NFX05PVEhJTkc7CisJZm9yIChpbnQgaSA9IDA7IGkgPCBsZW5ndGhvZihlbmRw b2ludF9hY3Rpb25zKTsgaSsrKQorCXsKKwkJaWYgKAorCQkJc3RybmNtcChidWYsIGVuZHBvaW50 X2FjdGlvbnNbaV0uZW5kcG9pbnQsIHN0cmxlbihlbmRwb2ludF9hY3Rpb25zW2ldLmVuZHBvaW50 KSkgPT0gMAorCQkJJiYKKwkJCShlbmRwb2ludF9hY3Rpb25zW2ldLnJlcXVpcmUgPT0gTlVMTAor CQkJIHx8CisJCQkgKihlbmRwb2ludF9hY3Rpb25zW2ldLnJlcXVpcmUpCisJCQkgKSkKKwkJewor CQkJdHlwZSA9IGVuZHBvaW50X2FjdGlvbnNbaV0udHlwZTsKKwkJCWJyZWFrOworCQl9CisJfQor CisJaWYgKHR5cGUgPT0gRVhQT1NFX05PVEhJTkcpCisJCXJldHVybiBmYWxzZTsKKworCXsKKwkJ c3RhdGljIGNvbnN0IGNoYXIgaHR0cF92ZXJzaW9uW10gPSAiSFRUUC8xLjEiOworCQlzdGF0aWMg Y29uc3QgY2hhciBodHRwX3R5cGVbXSA9ICJDb250ZW50LVR5cGU6IHRleHQvcGxhaW4iOworCQlz dGF0aWMgY29uc3QgY2hhciAqaHR0cF9jb25uID0gIkNvbm5lY3Rpb246IGNsb3NlIjsKKwkJc3Rh dGljIGNvbnN0IGNoYXIgaHR0cF9sZW5bXSA9ICJDb250ZW50LUxlbmd0aCI7CisKKwkJU3RyaW5n SW5mb0RhdGEgbXNnOworCisJCWlmICh0eXBlID09IEVYUE9TRV9IRUFEX1JFUExJQ0EpCisJCXsK KwkJCS8qCisJCQkgKiBDYWxsZXIgb25seSBjYXJlcyBhYm91dCB0aGUgSFRUUCByZXNwb25zZSBj b2RlLCBzbyBubyBjb250ZW50CisJCQkgKiBuZWVkZWQKKwkJCSAqLworCisJCQlpbml0U3RyaW5n SW5mb0V4dCgmbXNnLCA2NCk7CisKKwkJCWFwcGVuZFN0cmluZ0luZm8oJm1zZywKKwkJCQkJCQkg IiVzICVzXHJcbiIKKwkJCQkJCQkgIiVzXHJcbiIKKwkJCQkJCQkgIiVzXHJcblxyXG4iLAorCQkJ CQkJCSBodHRwX3ZlcnNpb24sCisJCQkJCQkJIChSZWNvdmVyeUluUHJvZ3Jlc3MoKSA/ICIyMDAg T0siIDogIjUwMyBTZXJ2aWNlIFVuYXZhaWxhYmxlIiksCisJCQkJCQkJIGh0dHBfdHlwZSwKKwkJ CQkJCQkgaHR0cF9jb25uCisJCQkJKTsKKwkJfQorCQllbHNlCisJCXsKKwkJCVN0cmluZ0luZm9E YXRhIGNvbnRlbnQ7CisKKwkJCWluaXRTdHJpbmdJbmZvRXh0KCZjb250ZW50LCA2NCk7CisKKwkJ CWlmIChleHBvc2VfcmVjb3ZlcnkgJiYgKHR5cGUgPT0gRVhQT1NFX0dFVF9BTEwgfHwgdHlwZSA9 PSBFWFBPU0VfR0VUX1JFUExJQ0EpKQorCQkJCWFwcGVuZFN0cmluZ0luZm8oJmNvbnRlbnQsICIl cyVkXHJcbiIsCisJCQkJCQkJCSB0eXBlID09IEVYUE9TRV9HRVRfQUxMID8gIlJFQ09WRVJZOiAi IDogIiIsCisJCQkJCQkJCSBSZWNvdmVyeUluUHJvZ3Jlc3MoKSA/IDEgOiAwKTsKKwkJCWlmIChl eHBvc2Vfc3lzaWQgJiYgKHR5cGUgPT0gRVhQT1NFX0dFVF9BTEwgfHwgdHlwZSA9PSBFWFBPU0Vf R0VUX1NZU0lEKSkKKwkJCQlhcHBlbmRTdHJpbmdJbmZvKCZjb250ZW50LCAiJXMlbHVcclxuIiwK KwkJCQkJCQkJIHR5cGUgPT0gRVhQT1NFX0dFVF9BTEwgPyAiU1lTSUQ6ICIgOiAiIiwKKwkJCQkJ CQkJIEdldFN5c3RlbUlkZW50aWZpZXIoKSk7CisJCQlpZiAoZXhwb3NlX3ZlcnNpb24gJiYgKHR5 cGUgPT0gRVhQT1NFX0dFVF9BTEwgfHwgdHlwZSA9PSBFWFBPU0VfR0VUX1ZFUlNJT04pKQorCQkJ CWFwcGVuZFN0cmluZ0luZm8oJmNvbnRlbnQsICIlcyVkXHJcbiIsCisJCQkJCQkJCSB0eXBlID09 IEVYUE9TRV9HRVRfQUxMID8gIlZFUlNJT046ICIgOiAiIiwKKwkJCQkJCQkJIFBHX1ZFUlNJT05f TlVNKTsKKworCQkJaW5pdFN0cmluZ0luZm9FeHQoJm1zZywgMjU2KTsKKworCQkJYXBwZW5kU3Ry aW5nSW5mbygmbXNnLAorCQkJCQkJCSAiJXMgMjAwIE9LXHJcbiIKKwkJCQkJCQkgIiVzXHJcbiIK KwkJCQkJCQkgIiVzOiAlZFxyXG4iCisJCQkJCQkJICIlc1xyXG5cclxuIgorCQkJCQkJCSAiJXMi LAorCQkJCQkJCSBodHRwX3ZlcnNpb24sCisJCQkJCQkJIGh0dHBfdHlwZSwKKwkJCQkJCQkgaHR0 cF9sZW4sIGNvbnRlbnQubGVuLAorCQkJCQkJCSBodHRwX2Nvbm4sCisJCQkJCQkJIGNvbnRlbnQu ZGF0YQorCQkJCSk7CisKKwkJCXBmcmVlKGNvbnRlbnQuZGF0YSk7CisJCX0KKworCQlkbworCQl7 CisJCQluID0gc2VuZChmZCwgbXNnLmRhdGEsIG1zZy5sZW4sIDApOworCQl9IHdoaWxlIChuIDwg MCAmJiBlcnJubyA9PSBFSU5UUik7CisKKwkJcGZyZWUobXNnLmRhdGEpOworCisJCWlmIChuIDwg MCkKKwkJCWVsb2coREVCVUcxLCAiY291bGQgbm90IHNlbmQgdG8gY2xpZW50OiAlbSIpOworCisJ CXJldHVybiB0cnVlOworCisJfQorCit9CmRpZmYgLS1naXQgYS9zcmMvYmFja2VuZC91dGlscy9t aXNjL2d1Y190YWJsZXMuYyBiL3NyYy9iYWNrZW5kL3V0aWxzL21pc2MvZ3VjX3RhYmxlcy5jCmlu ZGV4IDJmOGNiZDguLjM4YmVhNzEgMTAwNjQ0Ci0tLSBhL3NyYy9iYWNrZW5kL3V0aWxzL21pc2Mv Z3VjX3RhYmxlcy5jCisrKyBiL3NyYy9iYWNrZW5kL3V0aWxzL21pc2MvZ3VjX3RhYmxlcy5jCkBA IC0xNzAxLDYgKzE3MDEsMzMgQEAgc3RydWN0IGNvbmZpZ19ib29sIENvbmZpZ3VyZU5hbWVzQm9v bFtdID0KIAkJdHJ1ZSwKIAkJTlVMTCwgTlVMTCwgTlVMTAogCX0sCisJeworCQl7ImV4cG9zZV9y ZWNvdmVyeSIsIFBHQ19TSUdIVVAsIENMSUVOVF9DT05OX1NUQVRFTUVOVCwKKwkJCWdldHRleHRf bm9vcCgiRXhwb3NlcyBpZiB0aGUgc2VydmVyIGlzIGluIHJlY292ZXJ5IHdpdGhvdXQgYSBsb2dp bi4iKSwKKwkJCU5VTEwKKwkJfSwKKwkJJmV4cG9zZV9yZWNvdmVyeSwKKwkJZmFsc2UsCisJCU5V TEwsIE5VTEwsIE5VTEwKKwl9LAorCXsKKwkJeyJleHBvc2Vfc3lzaWQiLCBQR0NfU0lHSFVQLCBD TElFTlRfQ09OTl9TVEFURU1FTlQsCisJCQlnZXR0ZXh0X25vb3AoIkV4cG9zZXMgdGhlIHN5c3Rl bSBpZGVudGlmaWVyIHdpdGhvdXQgYSBsb2dpbi4iKSwKKwkJCU5VTEwKKwkJfSwKKwkJJmV4cG9z ZV9zeXNpZCwKKwkJZmFsc2UsCisJCU5VTEwsIE5VTEwsIE5VTEwKKwl9LAorCXsKKwkJeyJleHBv c2VfdmVyc2lvbiIsIFBHQ19TSUdIVVAsIENMSUVOVF9DT05OX1NUQVRFTUVOVCwKKwkJCWdldHRl eHRfbm9vcCgiRXhwb3NlcyB0aGUgdmVyc2lvbiB3aXRob3V0IGEgbG9naW4uIiksCisJCQlOVUxM CisJCX0sCisJCSZleHBvc2VfdmVyc2lvbiwKKwkJZmFsc2UsCisJCU5VTEwsIE5VTEwsIE5VTEwK Kwl9LAogCXsKIAkJeyJhcnJheV9udWxscyIsIFBHQ19VU0VSU0VULCBDT01QQVRfT1BUSU9OU19Q UkVWSU9VUywKIAkJCWdldHRleHRfbm9vcCgiRW5hYmxlcyBpbnB1dCBvZiBOVUxMIGVsZW1lbnRz IGluIGFycmF5cy4iKSwKZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL3V0aWxzL21pc2MvcG9zdGdy ZXNxbC5jb25mLnNhbXBsZSBiL3NyYy9iYWNrZW5kL3V0aWxzL21pc2MvcG9zdGdyZXNxbC5jb25m LnNhbXBsZQppbmRleCA4N2NlNzZiLi5hMTZkMzcyIDEwMDY0NAotLS0gYS9zcmMvYmFja2VuZC91 dGlscy9taXNjL3Bvc3RncmVzcWwuY29uZi5zYW1wbGUKKysrIGIvc3JjL2JhY2tlbmQvdXRpbHMv bWlzYy9wb3N0Z3Jlc3FsLmNvbmYuc2FtcGxlCkBAIC05MSw2ICs5MSwxNCBAQAogCQkJCQkjIGRp c2Nvbm5lY3Rpb24gd2hpbGUgcnVubmluZyBxdWVyaWVzOwogCQkJCQkjIDAgZm9yIG5ldmVyCiAK KworIyAtIEV4cG9zZSBpbmZvcm1hdGlvbiAtCisKKyNleHBvc2VfcmVjb3ZlcnkgPSBvZmYKKyNl eHBvc2Vfc3lzaWQgPSBvZmYKKyNleHBvc2VfdmVyc2lvbiA9IG9mZgorCisKICMgLSBBdXRoZW50 aWNhdGlvbiAtCiAKICNhdXRoZW50aWNhdGlvbl90aW1lb3V0ID0gMW1pbgkJIyAxcy02MDBzCmRp ZmYgLS1naXQgYS9zcmMvaW5jbHVkZS9wb3N0bWFzdGVyL3Bvc3RtYXN0ZXIuaCBiL3NyYy9pbmNs dWRlL3Bvc3RtYXN0ZXIvcG9zdG1hc3Rlci5oCmluZGV4IDkyNDk3Y2QuLjE1NjYyY2UgMTAwNjQ0 Ci0tLSBhL3NyYy9pbmNsdWRlL3Bvc3RtYXN0ZXIvcG9zdG1hc3Rlci5oCisrKyBiL3NyYy9pbmNs dWRlL3Bvc3RtYXN0ZXIvcG9zdG1hc3Rlci5oCkBAIC03MCw2ICs3MCwxMCBAQCBleHRlcm4gUEdE TExJTVBPUlQgYm9vbCByZXN0YXJ0X2FmdGVyX2NyYXNoOwogZXh0ZXJuIFBHRExMSU1QT1JUIGJv b2wgcmVtb3ZlX3RlbXBfZmlsZXNfYWZ0ZXJfY3Jhc2g7CiBleHRlcm4gUEdETExJTVBPUlQgYm9v bCBzZW5kX2Fib3J0X2Zvcl9jcmFzaDsKIGV4dGVybiBQR0RMTElNUE9SVCBib29sIHNlbmRfYWJv cnRfZm9yX2tpbGw7CitleHRlcm4gUEdETExJTVBPUlQgYm9vbCBleHBvc2VfcmVjb3Zlcnk7Citl eHRlcm4gUEdETExJTVBPUlQgYm9vbCBleHBvc2Vfc3lzaWQ7CitleHRlcm4gUEdETExJTVBPUlQg Ym9vbCBleHBvc2VfdmVyc2lvbjsKKwogCiAjaWZkZWYgV0lOMzIKIGV4dGVybiBQR0RMTElNUE9S VCBIQU5ETEUgUG9zdG1hc3RlckhhbmRsZTsKZGlmZiAtLWdpdCBhL3NyYy90ZXN0L3Bvc3RtYXN0 ZXIvdC8wMDRfZXhwb3NlZC5wbCBiL3NyYy90ZXN0L3Bvc3RtYXN0ZXIvdC8wMDRfZXhwb3NlZC5w bApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi45N2NjNmIxCi0tLSAvZGV2L251 bGwKKysrIGIvc3JjL3Rlc3QvcG9zdG1hc3Rlci90LzAwNF9leHBvc2VkLnBsCkBAIC0wLDAgKzEs MTA1IEBACisKKyMgQ29weXJpZ2h0IChjKSAyMDI1LCBQb3N0Z3JlU1FMIEdsb2JhbCBEZXZlbG9w bWVudCBHcm91cAorCisjIFRlc3QgcHJlLWZvcmsgSFRUUCBlbmRwb2ludCBpbmZvcm1hdGlvbgor Cit1c2Ugc3RyaWN0OwordXNlIHdhcm5pbmdzIEZBVEFMID0+ICdhbGwnOwordXNlIFBvc3RncmVT UUw6OlRlc3Q6OkNsdXN0ZXI7Cit1c2UgVGVzdDo6TW9yZTsKKworbXkgJG5vZGUgPSBQb3N0Z3Jl U1FMOjpUZXN0OjpDbHVzdGVyLT5uZXcoJ3ByaW1hcnknKTsKKyRub2RlLT5pbml0KCk7Ciskbm9k ZS0+c3RhcnQ7CisKK1NLSVA6Cit7CisJc2tpcCAidGhpcyB0ZXN0IHJlcXVpcmVzIHdvcmtpbmcg cmF3X2Nvbm5lY3QoKSIKKwkgIHVubGVzcyAkbm9kZS0+cmF3X2Nvbm5lY3Rfd29ya3MoKTsKKwor CW15ICgkZW5kcG9pbnQsICRzb2NrLCAkcmVwbHkpOworCisJJGVuZHBvaW50ID0gJ0dFVCAvaW5m byc7CisJJHNvY2sgPSAkbm9kZS0+cmF3X2Nvbm5lY3QoKTsKKwkkc29jay0+c2VuZCgkZW5kcG9p bnQpOworCSRzb2NrLT5yZWN2KCRyZXBseSwgMjAwKTsKKwlpcygkcmVwbHksICcnLCAibm90aGlu ZyBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkkc29jay0+Y2xvc2UoKTsKKworCSRlbmRw b2ludCA9ICdIRUFEIC9yZXBsaWNhJzsKKwkkc29jayA9ICRub2RlLT5yYXdfY29ubmVjdCgpOwor CSRzb2NrLT5zZW5kKCRlbmRwb2ludCk7CisJJHNvY2stPnJlY3YoJHJlcGx5LCAyMDApOworCWlz KCRyZXBseSwgJycsICJub3RoaW5nIGlzIHJldHVybmVkIGJ5ICRlbmRwb2ludCIpOworCisJJGVu ZHBvaW50ID0gJ0dFVCAvcmVwbGljYSc7CisJJHNvY2sgPSAkbm9kZS0+cmF3X2Nvbm5lY3QoKTsK Kwkkc29jay0+c2VuZCgkZW5kcG9pbnQpOworCSRzb2NrLT5yZWN2KCRyZXBseSwgMjAwKTsKKwlp cygkcmVwbHksICcnLCAibm90aGluZyBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkkc29j ay0+Y2xvc2UoKTsKKworCSRub2RlLT5hcHBlbmRfY29uZigncG9zdGdyZXNxbC5jb25mJywgImV4 cG9zZV9yZWNvdmVyeSA9IG9uIik7CisJJG5vZGUtPnJlbG9hZCgpOworCisJJHNvY2sgPSAkbm9k ZS0+cmF3X2Nvbm5lY3QoKTsKKwkkc29jay0+c2VuZCgkZW5kcG9pbnQpOworCSRzb2NrLT5yZWN2 KCRyZXBseSwgMjAwKTsKKwlsaWtlKCRyZXBseSwgcXJbXHJcbjBcYl0sICJyZWNvdmVyeSBpbmZv cm1hdGlvbiBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkkc29jay0+Y2xvc2UoKTsKKwor CSRlbmRwb2ludCA9ICdHRVQgL3N5c2lkJzsKKwkkc29jayA9ICRub2RlLT5yYXdfY29ubmVjdCgp OworCSRzb2NrLT5zZW5kKCRlbmRwb2ludCk7CisJJHNvY2stPnJlY3YoJHJlcGx5LCAyMDApOwor CWlzKCRyZXBseSwgJycsICJub3RoaW5nIGlzIHJldHVybmVkIGJ5ICRlbmRwb2ludCIpOworCSRz b2NrLT5jbG9zZSgpOworCisJJG5vZGUtPmFwcGVuZF9jb25mKCdwb3N0Z3Jlc3FsLmNvbmYnLCAi ZXhwb3NlX3N5c2lkID0gb24iKTsKKwkkbm9kZS0+cmVsb2FkKCk7CisKKwkkc29jayA9ICRub2Rl LT5yYXdfY29ubmVjdCgpOworCSRzb2NrLT5zZW5kKCRlbmRwb2ludCk7CisJJHNvY2stPnJlY3Yo JHJlcGx5LCAyMDApOworCWxpa2UoJHJlcGx5LCBxcltcclxuXGR7MTB9XSwgInN5c3RlbSBpZGVu dGlmaWVyIGlzIHJldHVybmVkIGJ5ICRlbmRwb2ludCIpOworCSRzb2NrLT5jbG9zZSgpOworCisJ JGVuZHBvaW50ID0gJ0dFVCAvdmVyc2lvbic7CisJJHNvY2sgPSAkbm9kZS0+cmF3X2Nvbm5lY3Qo KTsKKwkkc29jay0+c2VuZCgkZW5kcG9pbnQpOworCSRzb2NrLT5yZWN2KCRyZXBseSwgMjAwKTsK KwlpcygkcmVwbHksICcnLCAibm90aGluZyBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkk c29jay0+Y2xvc2UoKTsKKworCSRub2RlLT5hcHBlbmRfY29uZigncG9zdGdyZXNxbC5jb25mJywg ImV4cG9zZV92ZXJzaW9uID0gb24iKTsKKwkkbm9kZS0+cmVsb2FkKCk7CisKKwkkc29jayA9ICRu b2RlLT5yYXdfY29ubmVjdCgpOworCSRzb2NrLT5zZW5kKCRlbmRwb2ludCk7CisJJHNvY2stPnJl Y3YoJHJlcGx5LCAyMDApOworCWxpa2UoJHJlcGx5LCBxcltcclxuXGR7Nn1cYl0sICJ2ZXJzaW9u IG51bWJlciBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkkc29jay0+Y2xvc2UoKTsKKwor CisJJGVuZHBvaW50ID0gJ0dFVCAvaW5mbyc7CisJJHNvY2sgPSAkbm9kZS0+cmF3X2Nvbm5lY3Qo KTsKKwkkc29jay0+c2VuZCgkZW5kcG9pbnQpOworCSRzb2NrLT5yZWN2KCRyZXBseSwgMjAwKTsK KwlsaWtlKCRyZXBseSwgcXJbUkVDT1ZFUlk6IDBcYl0sICJyZWNvdmVyeSBpcyByZXR1cm5lZCBi eSAkZW5kcG9pbnQiKTsKKwlsaWtlKCRyZXBseSwgcXJbU1lTSUQ6IFxkezEwfV0sICJzeXNpZCBp cyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwlsaWtlKCRyZXBseSwgcXJbVkVSU0lPTjogXGR7 Nn1cYl0sICJ2ZXJzaW9uIG51bWJlciBpcyByZXR1cm5lZCBieSAkZW5kcG9pbnQiKTsKKwkkc29j ay0+Y2xvc2UoKTsKKworCSRlbmRwb2ludCA9ICdIRUFEIC9yZXBsaWNhJzsKKwkkc29jayA9ICRu b2RlLT5yYXdfY29ubmVjdCgpOworCSRzb2NrLT5zZW5kKCRlbmRwb2ludCk7CisJJHNvY2stPnJl Y3YoJHJlcGx5LCAyMDApOworCWxpa2UoJHJlcGx5LCBxcls1MDMgU2VydmljZSBVbmF2YWlsYWJs ZV0sICI1MDMgcmV0dXJuZWQgYnkgJGVuZHBvaW50Iik7CisJJHNvY2stPmNsb3NlKCk7CisKKwkj IyBOb3Qgd29ya2luZyB5ZXQ6CisJIyMgJG5vZGUtPmJhY2t1cCgndGVzdGJhY2t1cDEnKTsKKwor fQorCitkb25lX3Rlc3RpbmcoKTsKLS0gCjIuMzAuMgoK --000000000000b8deee0636472ea7--