stream: fix SYN_SENT RST/FIN injection

RST injection during the SYN_SENT state could trick Suricata into marking
a session as CLOSED. The way this was done is: using invalid TSECR value
in RST+ACK packet. The ACK was needed to force Linux into considering the
TSECR value and compare it to the TSVAL from the SYN packet.

The second works only against Windows. The client would not use a TSVAL
but the RST packet would. Windows will reject this, but Suricata considered
the RST valid and triggered the CLOSED logic.

This patch addresses both. When the SYN packet used timestamp support
the timestamp of incoming packet is validated. Otherwise, packet responding
should not have a timestamp.

Bug #3286

Reported-by: Nicolas Adba

@@ -1363,6 +1363,39 @@ static void StreamTcp3whsSynAckUpdate(TcpSession *ssn, Packet *p, TcpStateQueue
     ssn->flags &=~ STREAMTCP_FLAG_4WHS;
 }

+/** \internal
+ *  \brief detect timestamp anomalies when processing responses to the
+ *         SYN packet.
+ *  \retval true packet is ok
+ *  \retval false packet is bad
+ */
+static inline bool StateSynSentValidateTimestamp(TcpSession *ssn, Packet *p)
+{
+    /* we only care about evil server here, so skip TS packets */
+    if (PKT_IS_TOSERVER(p) || !(TCP_HAS_TS(p))) {
+        return true;
+    }
+
+    TcpStream *receiver_stream = &ssn->client;
+    uint32_t ts_echo = TCP_GET_TSECR(p);
+    if ((receiver_stream->flags & STREAMTCP_STREAM_FLAG_TIMESTAMP) != 0) {
+        if (receiver_stream->last_ts != 0 && ts_echo != 0 &&
+            ts_echo != receiver_stream->last_ts)
+        {
+            SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
+                    ts_echo, receiver_stream->last_ts);
+            return false;
+        }
+    } else {
+        if (receiver_stream->last_ts == 0 && ts_echo != 0) {
+            SCLogDebug("ssn %p: BAD TSECR echo %u recv %u", ssn,
+                    ts_echo, receiver_stream->last_ts);
+            return false;
+        }
+    }
+    return true;
+}
+
 /**
  *  \brief  Function to handle the TCP_SYN_SENT state. The function handles
  *          SYN, SYN/ACK, RST packets and correspondingly changes the connection
@@ -1382,6 +1415,10 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
     SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ?
                "toclient":"toserver");

+    /* check for bad responses */
+    if (StateSynSentValidateTimestamp(ssn, p) == false)
+        return -1;
+
     /* RST */
     if (p->tcph->th_flags & TH_RST) {
         if (!StreamTcpValidateRst(ssn, p))


floppy: check FDC index for errors before assigning it

Jordy Zomer reported a KASAN out-of-bounds read in the floppy driver in
wait_til_ready().

Which on the face of it can't happen, since as Willy Tarreau points out,
the function does no particular memory access.  Except through the FDCS
macro, which just indexes a static allocation through teh current fdc,
which is always checked against N_FDC.

Except the checking happens after we've already assigned the value.

The floppy driver is a disgrace (a lot of it going back to my original
horrd "design"), and has no real maintainer.  Nobody has the hardware,
and nobody really cares.  But it still gets used in virtual environment
because it's one of those things that everybody supports.

The whole thing should be re-written, or at least parts of it should be
seriously cleaned up.  The 'current fdc' index, which is used by the
FDCS macro, and which is often shadowed by a local 'fdc' variable, is a
prime example of how not to write code.

But because nobody has the hardware or the motivation, let's just fix up
the immediate problem with a nasty band-aid: test the fdc index before
actually assigning it to the static 'fdc' variable.

Reported-by: Jordy Zomer <jordy@simplyhacker.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+	unsigned int new_fdc = fdc;
+
 	if (drive >= 0 && drive < N_DRIVE) {
-		fdc = FDC(drive);
+		new_fdc = FDC(drive);
 		current_drive = drive;
 	}
-	if (fdc != 1 && fdc != 0) {
+	if (new_fdc >= N_FDC) {
 		pr_info("bad fdc value\n");
 		return;
 	}
+	fdc = new_fdc;
 	set_dor(fdc, ~0, 8);
 #if N_FDC > 1
 	set_dor(1 - fdc, ~8, 0);


command line triggered buffer overruns

Prevent extremely long command line arguments from overflowing local
buffers in raw_printf or config_error_add.  The increased buffer
sizes they recently got to deal with long configuration file values
aren't sufficient to handle command line induced overflows.

choose_windows(core): copy and truncate the window_type argument in
case it gets passed to config_error_add().

process_options(unix): report bad values with "%.60s" so that vsprintf
will implicitly truncate when formatted by raw_printf().

@@ -1000,6 +1000,7 @@ int uid;
  * print selected parts of score list.
  * argc >= 2, with argv[0] untrustworthy (directory names, et al.),
  * and argv[1] starting with "-s".
+ * caveat: some shells might allow argv elements to be arbitrarily long.
  */
 void
 prscore(argc, argv)


@@ -207,7 +207,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r);
 int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
 int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
 int sd_bus_flush(sd_bus *bus);
-int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m);
+int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);

 sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
 sd_bus_message* sd_bus_get_current_message(sd_bus *bus);


irc: fix crash when a new message 005 is received with longer nick prefixes

Thanks to Stuart Nevans Locke for reporting the issue.

@@ -643,6 +643,53 @@ irc_nick_set_mode (struct t_irc_server *server, struct t_irc_channel *channel,
     }
 }

+/*
+ * Reallocates the "prefixes" string in all nicks of all channels on the server
+ * (after 005 has been received).
+ */
+
+void
+irc_nick_realloc_prefixes (struct t_irc_server *server,
+                           int old_length, int new_length)
+{
+    struct t_irc_channel *ptr_channel;
+    struct t_irc_nick *ptr_nick;
+    char *new_prefixes;
+
+    for (ptr_channel = server->channels; ptr_channel;
+         ptr_channel = ptr_channel->next_channel)
+    {
+        for (ptr_nick = ptr_channel->nicks; ptr_nick;
+             ptr_nick = ptr_nick->next_nick)
+        {
+            if (ptr_nick->prefixes)
+            {
+                new_prefixes = realloc (ptr_nick->prefixes, new_length + 1);
+                if (new_prefixes)
+                {
+                    ptr_nick->prefixes = new_prefixes;
+                    if (new_length > old_length)
+                    {
+                        memset (ptr_nick->prefixes + old_length,
+                                ' ',
+                                new_length - old_length);
+                    }
+                    ptr_nick->prefixes[new_length] = '\0';
+                }
+            }
+            else
+            {
+                ptr_nick->prefixes = malloc (new_length + 1);
+                if (ptr_nick->prefixes)
+                {
+                    memset (ptr_nick->prefixes, ' ', new_length);
+                    ptr_nick->prefixes[new_length] = '\0';
+                }
+            }
+        }
+    }
+}
+
 /*
  * Removes a nick from a channel.
  */


Fix buffer overrun in SimpleParser::handleBackslash

Summary:
It read 4 chars, then checked for validity, but any of them could have
been the end of the string, so check after each one instead.

Reviewed By: oulgen

Differential Revision: D19611163

fbshipit-source-id: 3da0a39555cb85a93f4fd98048368f17cf37e2e4

@@ -453,12 +453,13 @@ struct SimpleParser {
       case 'u': {
         if (UNLIKELY(is_tsimplejson)) {
           auto const ch1 = *p++;
+          if (UNLIKELY(ch1 != '0')) return false;
           auto const ch2 = *p++;
+          if (UNLIKELY(ch2 != '0')) return false;
           auto const dch3 = dehexchar(*p++);
+          if (UNLIKELY(dch3 < 0)) return false;
           auto const dch4 = dehexchar(*p++);
-          if (UNLIKELY(ch1 != '0' || ch2 != '0' || dch3 < 0 || dch4 < 0)) {
-            return false;
-          }
+          if (UNLIKELY(dch4 < 0)) return false;
           out = (dch3 << 4) | dch4;
           return true;
         } else {


Fix OSS-Fuzz issue 20332: buffer overflow in jbig2_image_compose.

With extreme values of x/y/w/h we can get overflow. Test for this
and exit safely.

Thanks for OSS-Fuzz for reporting.

@@ -33,6 +33,9 @@
 #if !defined (INT32_MAX)
 #define INT32_MAX  0x7fffffff
 #endif
+#if !defined (UINT32_MAX)
+#define UINT32_MAX  0xffffffffu
+#endif

 /* allocate a Jbig2Image structure and its associated bitmap */
 Jbig2Image *
@@ -351,6 +354,15 @@ jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int
     if (src == NULL)
         return 0;

+    if ((UINT32_MAX - src->width  < (x > 0 ? x : -x)) ||
+        (UINT32_MAX - src->height < (y > 0 ? y : -y)))
+    {
+#ifdef JBIG2_DEBUG
+        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "overflow in compose_image");
+#endif
+        return 0;
+    }
+
     /* This code takes a src image and combines it onto dst at offset (x,y), with operation op. */

     /* Data is packed msb first within a byte, so with bits numbered: 01234567.


Merge pull request from GHSA-j2qp-rvxj-43vj

Fix setuid vulnerability

@@ -837,11 +837,13 @@ switch_to_user_with_privs (void)

 /* Call setuid() and use capset() to adjust capabilities */
 static void
-drop_privs (bool keep_requested_caps)
+drop_privs (bool keep_requested_caps,
+            bool already_changed_uid)
 {
   assert (!keep_requested_caps || !is_privileged);
   /* Drop root uid */
-  if (geteuid () == 0 && setuid (opt_sandbox_uid) < 0)
+  if (is_privileged && !already_changed_uid &&
+      setuid (opt_sandbox_uid) < 0)
     die_with_error ("unable to drop root uid");

   drop_all_caps (keep_requested_caps);
@@ -2299,6 +2301,9 @@ main (int    argc,
   if (opt_userns_fd != -1 && is_privileged)
     die ("--userns doesn't work in setuid mode");

+  if (opt_userns2_fd != -1 && is_privileged)
+    die ("--userns2 doesn't work in setuid mode");
+
   /* We have to do this if we weren't installed setuid (and we're not
    * root), so let's just DWIM */
   if (!is_privileged && getuid () != 0 && opt_userns_fd == -1)
@@ -2502,7 +2507,7 @@ main (int    argc,
         die_with_error ("Setting userns2 failed");

       /* We don't need any privileges in the launcher, drop them immediately. */
-      drop_privs (FALSE);
+      drop_privs (FALSE, FALSE);

       /* Optionally bind our lifecycle to that of the parent */
       handle_die_with_parent ();
@@ -2677,7 +2682,7 @@ main (int    argc,
       if (child == 0)
         {
           /* Unprivileged setup process */
-          drop_privs (FALSE);
+          drop_privs (FALSE, TRUE);
           close (privsep_sockets[0]);
           setup_newroot (opt_unshare_pid, privsep_sockets[1]);
           exit (0);
@@ -2775,7 +2780,7 @@ main (int    argc,
     }

   /* All privileged ops are done now, so drop caps we don't need */
-  drop_privs (!is_privileged);
+  drop_privs (!is_privileged, TRUE);

   if (opt_block_fd != -1)
     {


Fixed oob read in ntlm_read_AuthenticateMessage

@@ -681,15 +681,15 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu

 SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
 {
+	SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
 	wStream* s;
 	size_t length;
-	UINT32 flags;
-	NTLM_AV_PAIR* AvFlags;
+	UINT32 flags = 0;
+	NTLM_AV_PAIR* AvFlags = NULL;
 	UINT32 PayloadBufferOffset;
 	NTLM_AUTHENTICATE_MESSAGE* message;
 	SSPI_CREDENTIALS* credentials = context->credentials;
-	flags = 0;
-	AvFlags = NULL;
+
 	message = &context->AUTHENTICATE_MESSAGE;
 	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
 	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
@@ -698,130 +698,85 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		return SEC_E_INTERNAL_ERROR;

 	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (message->MessageType != MESSAGE_TYPE_AUTHENTICATE)
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) <
 	    0) /* LmChallengeResponseFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) <
 	    0) /* NtChallengeResponseFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) <
 	    0) /* EncryptedRandomSessionKeyFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

+	if (Stream_GetRemainingLength(s) < 4)
+		goto fail;
 	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
 	context->NegotiateKeyExchange =
 	    (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) ? TRUE : FALSE;

 	if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) ||
 	    (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len))
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;

 	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
 	{
 		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;
 	}

 	PayloadBufferOffset = Stream_GetPosition(s);

+	status = SEC_E_INTERNAL_ERROR;
 	if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) <
 	    0) /* LmChallengeResponse */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) <
 	    0) /* NtChallengeResponse */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (message->NtChallengeResponse.Len > 0)
 	{
+		int rc;
 		size_t cbAvFlags;
 		wStream* snt =
 		    Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);

 		if (!snt)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
-
-		if (ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)) < 0)
-		{
-			Stream_Free(s, FALSE);
-			Stream_Free(snt, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;

+		status = SEC_E_INVALID_TOKEN;
+		rc = ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response));
 		Stream_Free(snt, FALSE);
+		if (rc < 0)
+			goto fail;
+		status = SEC_E_INTERNAL_ERROR;
+
 		context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer;
 		context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
 		sspi_SecBufferFree(&(context->ChallengeTargetInfo));
@@ -838,18 +793,12 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer

 	if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) <
 	    0) /* EncryptedRandomSessionKey */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	if (message->EncryptedRandomSessionKey.Len > 0)
 	{
 		if (message->EncryptedRandomSessionKey.Len != 16)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;

 		CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer,
 		           16);
@@ -858,10 +807,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	length = Stream_GetPosition(s);

 	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;

 	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
 	buffer->cbBuffer = length;
@@ -871,15 +817,15 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	{
 		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);

+		status = SEC_E_INVALID_TOKEN;
 		if (Stream_GetRemainingLength(s) < 16)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;

 		Stream_Read(s, message->MessageIntegrityCheck, 16);
 	}

+	status = SEC_E_INTERNAL_ERROR;
+
 #ifdef WITH_DEBUG_NTLM
 	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %" PRIu32 ")",
 	         context->AuthenticateMessage.cbBuffer);
@@ -911,10 +857,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		credentials->identity.User = (UINT16*)malloc(message->UserName.Len);

 		if (!credentials->identity.User)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
+			goto fail;

 		CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len);
 		credentials->identity.UserLength = message->UserName.Len / 2;
@@ -925,10 +868,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		credentials->identity.Domain = (UINT16*)malloc(message->DomainName.Len);

 		if (!credentials->identity.Domain)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
+			goto fail;

 		CopyMemory(credentials->identity.Domain, message->DomainName.Buffer,
 		           message->DomainName.Len);
@@ -939,6 +879,10 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	/* Computations beyond this point require the NTLM hash of the password */
 	context->state = NTLM_STATE_COMPLETION;
 	return SEC_I_COMPLETE_NEEDED;
+
+fail:
+	Stream_Free(s, FALSE);
+	return status;
 }

 /**


Fixed  GHSL-2020-102 heap overflow

(cherry picked from commit 197b16cc15a12813c2e4fa2d6ae9cd9c4a57e581)

@@ -96,13 +96,24 @@ BOOL crypto_cert_get_public_key(CryptoCert cert, BYTE** PublicKey, DWORD* Public
 static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus,
                              const BYTE* exponent, int exponent_size, BYTE* output)
 {
-	BN_CTX* ctx;
+	BN_CTX* ctx = NULL;
 	int output_length = -1;
-	BYTE* input_reverse;
-	BYTE* modulus_reverse;
-	BYTE* exponent_reverse;
-	BIGNUM *mod, *exp, *x, *y;
-	input_reverse = (BYTE*)malloc(2 * key_length + exponent_size);
+	BYTE* input_reverse = NULL;
+	BYTE* modulus_reverse = NULL;
+	BYTE* exponent_reverse = NULL;
+	BIGNUM* mod = NULL;
+	BIGNUM* exp = NULL;
+	BIGNUM* x = NULL;
+	BIGNUM* y = NULL;
+	size_t bufferSize = 2 * key_length + exponent_size;
+
+	if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output)
+		return -1;
+
+	if (length > bufferSize)
+		bufferSize = length;
+
+	input_reverse = (BYTE*)calloc(bufferSize, 1);

 	if (!input_reverse)
 		return -1;
@@ -131,16 +142,24 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
 	if (!(y = BN_new()))
 		goto fail_bn_y;

-	BN_bin2bn(modulus_reverse, key_length, mod);
-	BN_bin2bn(exponent_reverse, exponent_size, exp);
-	BN_bin2bn(input_reverse, length, x);
-	BN_mod_exp(y, x, exp, mod, ctx);
+	if (!BN_bin2bn(modulus_reverse, key_length, mod))
+		goto fail;
+
+	if (!BN_bin2bn(exponent_reverse, exponent_size, exp))
+		goto fail;
+	if (!BN_bin2bn(input_reverse, length, x))
+		goto fail;
+	if (BN_mod_exp(y, x, exp, mod, ctx) != 1)
+		goto fail;
 	output_length = BN_bn2bin(y, output);
+	if (output_length < 0)
+		goto fail;
 	crypto_reverse(output, output_length);

-	if (output_length < (int)key_length)
+	if (output_length < key_length)
 		memset(output + output_length, 0, key_length - output_length);

+fail:
 	BN_free(y);
 fail_bn_y:
 	BN_clear_free(x);


sanity checks for client-supplied OK packet content

reported by Matthias Kaiser, Apple Information Security

@@ -81,6 +81,8 @@
 #define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
 #define MA_RPL_VERSION_HACK "5.5.5-"

+#define CHARSET_NAME_LEN 64
+
 #undef max_allowed_packet
 #undef net_buffer_length
 extern ulong max_allowed_packet; /* net.c */
@@ -2139,17 +2141,22 @@ mysql_send_query(MYSQL* mysql, const char* query, unsigned long length)

 int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
 {
+  uchar *end= mysql->net.read_pos+length;
   size_t item_len;
   mysql->affected_rows= net_field_length_ll(&pos);
   mysql->insert_id=	  net_field_length_ll(&pos);
   mysql->server_status=uint2korr(pos);
   pos+=2;
   mysql->warning_count=uint2korr(pos);
   pos+=2;
-  if (pos < mysql->net.read_pos+length)
+  if (pos > end)
+    goto corrupted;
+  if (pos < end)
   {
     if ((item_len= net_field_length(&pos)))
       mysql->info=(char*) pos;
+    if (pos + item_len > end)
+      goto corrupted;

     /* check if server supports session tracking */
     if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
@@ -2160,23 +2167,26 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
       if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
       {
         int i;
-        if (pos < mysql->net.read_pos + length)
+        if (pos < end)
         {
           LIST *session_item;
           MYSQL_LEX_STRING *str= NULL;
           enum enum_session_state_type si_type;
           uchar *old_pos= pos;
-          size_t item_len= net_field_length(&pos);  /* length for all items */
+
+          item_len= net_field_length(&pos);  /* length for all items */
+          if (pos + item_len > end)
+            goto corrupted;
+          end= pos + item_len;

           /* length was already set, so make sure that info will be zero terminated */
           if (mysql->info)
             *old_pos= 0;

-          while (item_len > 0)
+          while (pos < end)
           {
             size_t plen;
             char *data;
-            old_pos= pos;
             si_type= (enum enum_session_state_type)net_field_length(&pos);
             switch(si_type) {
             case SESSION_TRACK_SCHEMA:
@@ -2186,16 +2196,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
               if (si_type != SESSION_TRACK_STATE_CHANGE)
                 net_field_length(&pos); /* ignore total length, item length will follow next */
               plen= net_field_length(&pos);
+              if (pos + plen > end)
+                goto corrupted;
               if (!(session_item= ma_multi_malloc(0,
                                   &session_item, sizeof(LIST),
                                   &str, sizeof(MYSQL_LEX_STRING),
                                   &data, plen,
                                   NULL)))
-              {
-                ma_clear_session_state(mysql);
-                SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
-                return -1;
-              }
+                  goto oom;
               str->length= plen;
               str->str= data;
               memcpy(str->str, (char *)pos, plen);
@@ -2218,41 +2226,40 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
                 if (!strncmp(str->str, "character_set_client", str->length))
                   set_charset= 1;
                 plen= net_field_length(&pos);
+                if (pos + plen > end)
+                  goto corrupted;
                 if (!(session_item= ma_multi_malloc(0,
                                     &session_item, sizeof(LIST),
                                     &str, sizeof(MYSQL_LEX_STRING),
                                     &data, plen,
                                     NULL)))
-                {
-                  ma_clear_session_state(mysql);
-                  SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
-                  return -1;
-                }
+                  goto oom;
                 str->length= plen;
                 str->str= data;
                 memcpy(str->str, (char *)pos, plen);
                 pos+= plen;
                 session_item->data= str;
                 mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
-                if (set_charset &&
+                if (set_charset && str->length < CHARSET_NAME_LEN &&
                     strncmp(mysql->charset->csname, str->str, str->length) != 0)
                 {
-                  char cs_name[64];
-                  MARIADB_CHARSET_INFO *cs_info;
+                  char cs_name[CHARSET_NAME_LEN];
+                  const MARIADB_CHARSET_INFO *cs_info;
                   memcpy(cs_name, str->str, str->length);
                   cs_name[str->length]= 0;
-                  if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name)))
+                  if ((cs_info = mysql_find_charset_name(cs_name)))
                     mysql->charset= cs_info;
                 }
               }
               break;
             default:
               /* not supported yet */
               plen= net_field_length(&pos);
+              if (pos + plen > end)
+                goto corrupted;
               pos+= plen;
               break;
             }
-            item_len-= (pos - old_pos);
           }
         }
         for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
@@ -2267,6 +2274,16 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
   else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
     ma_clear_session_state(mysql);
   return(0);
+
+oom:
+  ma_clear_session_state(mysql);
+  SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+  return -1;
+
+corrupted:
+  ma_clear_session_state(mysql);
+  SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+  return -1;
 }

 int mthd_my_read_query_result(MYSQL *mysql)


@@ -98,139 +98,6 @@ BOOL xf_decode_color(xfContext* xfc, const UINT32 srcColor, XColor* color)
 	return TRUE;
 }

-/* Bitmap Class */
-static BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
-{
-	BOOL rc = FALSE;
-	UINT32 depth;
-	BYTE* data;
-	rdpGdi* gdi;
-	xfBitmap* xbitmap = (xfBitmap*)bitmap;
-	xfContext* xfc = (xfContext*)context;
-
-	if (!context || !bitmap || !context->gdi)
-		return FALSE;
-
-	gdi = context->gdi;
-	xf_lock_x11(xfc);
-	depth = FreeRDPGetBitsPerPixel(bitmap->format);
-
-	WINPR_ASSERT(xfc->depth != 0);
-	xbitmap->pixmap =
-	    XCreatePixmap(xfc->display, xfc->drawable, bitmap->width, bitmap->height, xfc->depth);
-
-	if (!xbitmap->pixmap)
-		goto unlock;
-
-	if (bitmap->data)
-	{
-		XSetFunction(xfc->display, xfc->gc, GXcopy);
-
-		if ((INT64)depth != xfc->depth)
-		{
-			if (!(data = winpr_aligned_malloc(bitmap->width * bitmap->height * 4ULL, 16)))
-				goto unlock;
-
-			if (!freerdp_image_copy(data, gdi->dstFormat, 0, 0, 0, bitmap->width, bitmap->height,
-			                        bitmap->data, bitmap->format, 0, 0, 0, &context->gdi->palette,
-			                        FREERDP_FLIP_NONE))
-			{
-				winpr_aligned_free(data);
-				goto unlock;
-			}
-
-			winpr_aligned_free(bitmap->data);
-			bitmap->data = data;
-			bitmap->format = gdi->dstFormat;
-		}
-
-		WINPR_ASSERT(xfc->depth != 0);
-		xbitmap->image =
-		    XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*)bitmap->data,
-		                 bitmap->width, bitmap->height, xfc->scanline_pad, 0);
-
-		if (!xbitmap->image)
-			goto unlock;
-
-		xbitmap->image->byte_order = LSBFirst;
-		xbitmap->image->bitmap_bit_order = LSBFirst;
-		XPutImage(xfc->display, xbitmap->pixmap, xfc->gc, xbitmap->image, 0, 0, 0, 0, bitmap->width,
-		          bitmap->height);
-	}
-
-	rc = TRUE;
-unlock:
-	xf_unlock_x11(xfc);
-	return rc;
-}
-
-static void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
-{
-	xfContext* xfc = (xfContext*)context;
-	xfBitmap* xbitmap = (xfBitmap*)bitmap;
-
-	if (!xfc || !xbitmap)
-		return;
-
-	xf_lock_x11(xfc);
-
-	if (xbitmap->pixmap != 0)
-	{
-		XFreePixmap(xfc->display, xbitmap->pixmap);
-		xbitmap->pixmap = 0;
-	}
-
-	if (xbitmap->image)
-	{
-		xbitmap->image->data = NULL;
-		XDestroyImage(xbitmap->image);
-		xbitmap->image = NULL;
-	}
-
-	xf_unlock_x11(xfc);
-	winpr_aligned_free(bitmap->data);
-	free(xbitmap);
-}
-
-static BOOL xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
-{
-	int width, height;
-	xfContext* xfc = (xfContext*)context;
-	xfBitmap* xbitmap = (xfBitmap*)bitmap;
-	BOOL ret;
-
-	if (!context || !xbitmap)
-		return FALSE;
-
-	width = bitmap->right - bitmap->left + 1;
-	height = bitmap->bottom - bitmap->top + 1;
-	xf_lock_x11(xfc);
-	XSetFunction(xfc->display, xfc->gc, GXcopy);
-	XPutImage(xfc->display, xfc->primary, xfc->gc, xbitmap->image, 0, 0, bitmap->left, bitmap->top,
-	          width, height);
-	ret = gdi_InvalidateRegion(xfc->hdc, bitmap->left, bitmap->top, width, height);
-	xf_unlock_x11(xfc);
-	return ret;
-}
-
-static BOOL xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
-{
-	xfContext* xfc = (xfContext*)context;
-
-	if (!context || (!bitmap && !primary))
-		return FALSE;
-
-	xf_lock_x11(xfc);
-
-	if (primary)
-		xfc->drawing = xfc->primary;
-	else
-		xfc->drawing = ((xfBitmap*)bitmap)->pixmap;
-
-	xf_unlock_x11(xfc);
-	return TRUE;
-}
-
 static BOOL xf_Pointer_GetCursorForCurrentScale(rdpContext* context, rdpPointer* pointer,
                                                 Cursor* cursor)
 {
@@ -630,23 +497,6 @@ BOOL xf_register_pointer(rdpGraphics* graphics)
 	return TRUE;
 }

-BOOL xf_register_graphics(rdpGraphics* graphics)
-{
-	rdpBitmap bitmap;
-
-	if (!graphics || !graphics->Bitmap_Prototype || !graphics->Glyph_Prototype)
-		return FALSE;
-
-	bitmap = *graphics->Bitmap_Prototype;
-	bitmap.size = sizeof(xfBitmap);
-	bitmap.New = xf_Bitmap_New;
-	bitmap.Free = xf_Bitmap_Free;
-	bitmap.Paint = xf_Bitmap_Paint;
-	bitmap.SetSurface = xf_Bitmap_SetSurface;
-	graphics_register_bitmap(graphics, &bitmap);
-	return TRUE;
-}
-
 UINT32 xf_get_local_color_format(xfContext* xfc, BOOL aligned)
 {
 	UINT32 DstFormat;


@@ -177,7 +177,6 @@ struct xf_context
 	BOOL UseXThreads;
 	BOOL cursorHidden;

-	HGDI_DC hdc;
 	UINT32 bitmap_size;
 	BYTE* bitmap_buffer;


Merge pull request #6019 from akallabeth/bound_access_fixes

Fix issues with boundary access.

@@ -281,11 +281,12 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
 	bitmapCache->settings = settings;
 	bitmapCache->update = ((freerdp*)settings->instance)->update;
 	bitmapCache->context = bitmapCache->update->context;
-	bitmapCache->maxCells = settings->BitmapCacheV2NumCells;
-	bitmapCache->cells = (BITMAP_V2_CELL*)calloc(bitmapCache->maxCells, sizeof(BITMAP_V2_CELL));
+	bitmapCache->cells =
+	    (BITMAP_V2_CELL*)calloc(settings->BitmapCacheV2NumCells, sizeof(BITMAP_V2_CELL));

 	if (!bitmapCache->cells)
 		goto fail;
+	bitmapCache->maxCells = settings->BitmapCacheV2NumCells;

 	for (i = 0; i < (int)bitmapCache->maxCells; i++)
 	{


Fix #6010: Check length in read_icon_info

@@ -136,9 +136,6 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
 	Stream_Read_UINT16(s, iconInfo->cbBitsMask);  /* cbBitsMask (2 bytes) */
 	Stream_Read_UINT16(s, iconInfo->cbBitsColor); /* cbBitsColor (2 bytes) */

-	if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask + iconInfo->cbBitsColor)
-		return FALSE;
-
 	/* bitsMask */
 	newBitMask = (BYTE*)realloc(iconInfo->bitsMask, iconInfo->cbBitsMask);

@@ -150,6 +147,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
 	}

 	iconInfo->bitsMask = newBitMask;
+	if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask)
+		return FALSE;
 	Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask);

 	/* colorTable */
@@ -184,7 +183,11 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
 	}

 	if (iconInfo->colorTable)
+	{
+		if (Stream_GetRemainingLength(s) < iconInfo->cbColorTable)
+			return FALSE;
 		Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable);
+	}

 	/* bitsColor */
 	newBitMask = (BYTE*)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor);
@@ -197,6 +200,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
 	}

 	iconInfo->bitsColor = newBitMask;
+	if (Stream_GetRemainingLength(s) < iconInfo->cbBitsColor)
+		return FALSE;
 	Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
 	return TRUE;
 }


Constant time EC map to affine for private operations

For fast math, use a constant time modular inverse when mapping to
affine when operation involves a private key - key gen, calc shared
secret, sign.

@@ -439,6 +439,7 @@ ECC_API int ecc_mul2add(ecc_point* A, mp_int* kA,
                 ecc_point* C, mp_int* a, mp_int* modulus, void* heap);

 ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit);
+ECC_API int ecc_map_ex(ecc_point*, mp_int*, mp_digit, int ct);
 ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
                                      mp_int* a, mp_int* modulus, mp_digit mp);
 ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a,


Fixed OOB Read in license_read_new_or_upgrade_license_packet

CVE-2020-11099 thanks to @antonio-morales for finding this.

@@ -1252,6 +1252,9 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
 	if (!licenseStream)
 		goto out_free_blob;

+	if (Stream_GetRemainingLength(licenseStream) < 8)
+		goto out_free_stream;
+
 	Stream_Read_UINT16(licenseStream, os_minor);
 	Stream_Read_UINT16(licenseStream, os_major);

@@ -1266,6 +1269,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
 	Stream_Seek(licenseStream, cbScope);

 	/* CompanyName */
+	if (Stream_GetRemainingLength(licenseStream) < 4)
+		goto out_free_stream;
 	Stream_Read_UINT32(licenseStream, cbCompanyName);
 	if (Stream_GetRemainingLength(licenseStream) < cbCompanyName)
 		goto out_free_stream;
@@ -1276,6 +1281,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
 	Stream_Seek(licenseStream, cbCompanyName);

 	/* productId */
+	if (Stream_GetRemainingLength(licenseStream) < 4)
+		goto out_free_stream;
 	Stream_Read_UINT32(licenseStream, cbProductId);
 	if (Stream_GetRemainingLength(licenseStream) < cbProductId)
 		goto out_free_stream;
@@ -1286,6 +1293,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
 	Stream_Seek(licenseStream, cbProductId);

 	/* licenseInfo */
+	if (Stream_GetRemainingLength(licenseStream) < 4)
+		goto out_free_stream;
 	Stream_Read_UINT32(licenseStream, cbLicenseInfo);
 	if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo)
 		goto out_free_stream;


tls: clear data after a starttls acknowledgement

After a starttls acknowledgement message, clear the buffers of any
incoming data / commands.  This will ensure that all future data is
handled securely.

Co-authored-by: Pietro Cerutti <gahr@gahr.ch>

@@ -301,3 +301,23 @@ struct Connection *mutt_socket_new(enum ConnectionType type)

   return conn;
 }
+
+/**
+ * mutt_socket_empty - Clear out any queued data
+ *
+ * The internal buffer is emptied and any data that has already arrived at this
+ * machine (in kernel buffers) is read and dropped.
+ */
+void mutt_socket_empty(struct Connection *conn)
+{
+  if (!conn)
+    return;
+
+  char buf[1024];
+  int bytes;
+
+  while ((bytes = mutt_socket_poll(conn, 0)) > 0)
+  {
+    mutt_socket_read(conn, buf, MIN(bytes, sizeof(buf)));
+  }
+}


xsk: Add missing check on user supplied headroom size

Add a check that the headroom cannot be larger than the available
space in the chunk. In the current code, a malicious user can set the
headroom to a value larger than the chunk size minus the fixed XDP
headroom. That way packets with a length larger than the supported
size in the umem could get accepted and result in an out-of-bounds
write.

Fixes: c0c77d8fb787 ("xsk: add user memory registration support sockopt")
Reported-by: Bui Quang Minh <minhquangbui99@gmail.com>
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=207225
Link: https://lore.kernel.org/bpf/1586849715-23490-1-git-send-email-magnus.karlsson@intel.com

@@ -343,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 	u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
 	unsigned int chunks, chunks_per_page;
 	u64 addr = mr->addr, size = mr->len;
-	int size_chk, err;
+	int err;

 	if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
 		/* Strictly speaking we could support this, if:
@@ -382,8 +382,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 			return -EINVAL;
 	}

-	size_chk = chunk_size - headroom - XDP_PACKET_HEADROOM;
-	if (size_chk < 0)
+	if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
 		return -EINVAL;

 	umem->address = (unsigned long)addr;


libvncserver: encodings: prevent OOB accesses

@@ -233,7 +233,7 @@ subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) {
             seg = data+(j*w);                                                 \
             if (seg[x] != cl) {break;}                                        \
             i = x;                                                            \
-            while ((seg[i] == cl) && (i < w)) i += 1;                         \
+            while ((i < w) && (seg[i] == cl)) i += 1;                         \
             i -= 1;                                                           \
             if (j == y) vx = hx = i;                                          \
             if (i < vx) vx = i;                                               \


mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()

mwifiex_ret_wmm_get_status() calls memcpy() without checking the
destination size.Since the source is given from remote AP which
contains illegal wmm elements , this may trigger a heap buffer
overflow.
Fix it by putting the length check before calling memcpy().

Signed-off-by: Qing Xu <m1s5p6688@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

@@ -970,6 +970,10 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
 				    "WMM Parameter Set Count: %d\n",
 				    wmm_param_ie->qos_info_bitmap & mask);

+			if (wmm_param_ie->vend_hdr.len + 2 >
+				sizeof(struct ieee_types_wmm_parameter))
+				break;
+
 			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
 			       wmm_ie, wmm_param_ie,
 			       wmm_param_ie->vend_hdr.len + 2);


mm: mempolicy: require at least one nodeid for MPOL_PREFERRED

Using an empty (malformed) nodelist that is not caught during mount option
parsing leads to a stack-out-of-bounds access.

The option string that was used was: "mpol=prefer:,".  However,
MPOL_PREFERRED requires a single node number, which is not being provided
here.

Add a check that 'nodes' is not empty after parsing for MPOL_PREFERRED's
nodeid.

Fixes: 095f1fc4ebf3 ("mempolicy: rework shmem mpol parsing and display")
Reported-by: Entropy Moe <3ntr0py1337@gmail.com>
Reported-by: syzbot+b055b1a6b2b958707a21@syzkaller.appspotmail.com
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: syzbot+b055b1a6b2b958707a21@syzkaller.appspotmail.com
Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
Link: http://lkml.kernel.org/r/89526377-7eb6-b662-e1d8-4430928abde9@infradead.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

@@ -2898,14 +2898,18 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
 	switch (mode) {
 	case MPOL_PREFERRED:
 		/*
-		 * Insist on a nodelist of one node only
+		 * Insist on a nodelist of one node only, although later
+		 * we use first_node(nodes) to grab a single node, so here
+		 * nodelist (or nodes) cannot be empty.
 		 */
 		if (nodelist) {
 			char *rest = nodelist;
 			while (isdigit(*rest))
 				rest++;
 			if (*rest)
 				goto out;
+			if (nodes_empty(nodes))
+				goto out;
 		}
 		break;
 	case MPOL_INTERLEAVE:


@@ -458,6 +458,7 @@ static int session_new(nghttp2_session **session_ptr,

   (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
   (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
+  (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;

   if (option) {
     if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
@@ -521,6 +522,11 @@ static int session_new(nghttp2_session **session_ptr,
     if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
       (*session_ptr)->max_outbound_ack = option->max_outbound_ack;
     }
+
+    if ((option->opt_set_mask & NGHTTP2_OPT_MAX_SETTINGS) &&
+        option->max_settings) {
+      (*session_ptr)->max_settings = option->max_settings;
+    }
   }

   rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@@ -5657,6 +5663,16 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
           iframe->max_niv =
               iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;

+          if (iframe->max_niv - 1 > session->max_settings) {
+            rv = nghttp2_session_terminate_session_with_reason(
+                session, NGHTTP2_ENHANCE_YOUR_CALM,
+                "SETTINGS: too many setting entries");
+            if (nghttp2_is_fatal(rv)) {
+              return rv;
+            }
+            return (ssize_t)inlen;
+          }
+
           iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
                                                    iframe->max_niv);

@@ -7425,6 +7441,11 @@ static int nghttp2_session_upgrade_internal(nghttp2_session *session,
   if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
     return NGHTTP2_ERR_INVALID_ARGUMENT;
   }
+  /* SETTINGS frame contains too many settings */
+  if (settings_payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH
+        > session->max_settings) {
+    return NGHTTP2_ERR_TOO_MANY_SETTINGS;
+  }
   rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
                                               settings_payloadlen, mem);
   if (rv != 0) {


random32: update the net random state on interrupt and activity

This modifies the first 32 bits out of the 128 bits of a random CPU's
net_rand_state on interrupt or CPU activity to complicate remote
observations that could lead to guessing the network RNG's internal
state.

Note that depending on some network devices' interrupt rate moderation
or binding, this re-seeding might happen on every packet or even almost
never.

In addition, with NOHZ some CPUs might not even get timer interrupts,
leaving their local state rarely updated, while they are running
networked processes making use of the random state.  For this reason, we
also perform this update in update_process_times() in order to at least
update the state when there is user or system activity, since it's the
only case we care about.

Reported-by: Amit Klein <aksecurity@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/once.h>
+#include <linux/percpu.h>

 #include <uapi/linux/random.h>

@@ -119,6 +120,8 @@ struct rnd_state {
 	__u32 s1, s2, s3, s4;
 };

+DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
+
 u32 prandom_u32_state(struct rnd_state *state);
 void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
 void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);


encode: protect from stack under-flow

From GH #178 fuzzing

@@ -953,7 +953,7 @@ bit_write_UMC (Bit_Chain *dat, BITCODE_UMC val)
     if (byte[i] & 0x7f)
       break;

-  if (byte[i] & 0x40)
+  if (byte[i] & 0x40 && i > 0)
     i--;
   byte[i] &= 0x7f;
   for (j = 4; j >= i; j--)


Fixed bugs of stack reallocation x GC

Macro 'checkstackGC' was doing a GC step after resizing the stack;
the GC could shrink the stack and undo the resize. Moreover, macro
'checkstackp' also does a GC step, which could remove the preallocated
CallInfo when calling a function. (Its name has been changed to
'checkstackGCp' to emphasize that it calls the GC.)

@@ -17,6 +17,8 @@
 ** Macro to check stack size and grow stack if needed.  Parameters
 ** 'pre'/'pos' allow the macro to preserve a pointer into the
 ** stack across reallocations, doing the work only when needed.
+** It also allows the running of one GC step when the stack is
+** reallocated.
 ** 'condmovestack' is used in heavy tests to force a stack reallocation
 ** at every check.
 */
@@ -35,7 +37,7 @@

 /* macro to check stack size, preserving 'p' */
-#define checkstackp(L,n,p)  \
+#define checkstackGCp(L,n,p)  \
   luaD_checkstackaux(L, n, \
     ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
     luaC_checkGC(L),  /* stack grow uses memory */ \
@@ -44,7 +46,7 @@

 /* macro to check stack size and GC */
 #define checkstackGC(L,fsize)  \
-	luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L))
+	luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)

 /* type of protected functions, to be ran by 'runprotected' */


@@ -33,6 +33,25 @@ int LibRaw::unpack_thumb(void)
   CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
   CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);

+#define THUMB_SIZE_CHECKT(A) \
+  do { \
+    if (INT64(A) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+    if (INT64(A) > 0 &&  INT64(A) < 64ULL)        throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+  } while (0)
+
+#define THUMB_SIZE_CHECKTNZ(A) \
+  do { \
+    if (INT64(A) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+    if (INT64(A) < 64ULL)        throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+  } while (0)
+
+
+#define THUMB_SIZE_CHECKWH(W,H) \
+  do { \
+    if (INT64(W)*INT64(H) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+    if (INT64(W)*INT64(H) < 64ULL)        throw LIBRAW_EXCEPTION_IO_CORRUPT; \
+  } while (0)
+
   try
   {
     if (!libraw_internal_data.internal_data.input)
@@ -65,6 +84,7 @@ int LibRaw::unpack_thumb(void)

         if (INT64(ID.toffset) + tsize > ID.input->size() + THUMB_READ_BEYOND)
           throw LIBRAW_EXCEPTION_IO_EOF;
+        THUMB_SIZE_CHECKT(tsize);
       }
 #else
 	if (0) {}
@@ -82,6 +102,8 @@ int LibRaw::unpack_thumb(void)
       ID.input->seek(ID.toffset, SEEK_SET);
       if (write_thumb == &LibRaw::jpeg_thumb)
       {
+        THUMB_SIZE_CHECKTNZ(T.tlength);
+
         if (T.thumb)
           free(T.thumb);
         T.thumb = (char *)malloc(T.tlength);
@@ -132,6 +154,8 @@ int LibRaw::unpack_thumb(void)
         if (colors != 1 && colors != 3)
           return LIBRAW_UNSUPPORTED_THUMBNAIL;

+        THUMB_SIZE_CHECKWH(T.twidth, T.theight);
+
         int tlength = T.twidth * T.theight;
         if (T.thumb)
           free(T.thumb);
@@ -172,6 +196,7 @@ int LibRaw::unpack_thumb(void)
       else if (write_thumb == &LibRaw::rollei_thumb)
       {
         int i;
+        THUMB_SIZE_CHECKWH(T.twidth, T.theight);
         int tlength = T.twidth * T.theight;
         if (T.thumb)
           free(T.thumb);
@@ -198,6 +223,7 @@ int LibRaw::unpack_thumb(void)
         if (t_bytesps > 1)
           throw LIBRAW_EXCEPTION_IO_CORRUPT; // 8-bit thumb, but parsed for more
                                              // bits
+        THUMB_SIZE_CHECKWH(T.twidth, T.theight);
         int t_length = T.twidth * T.theight * t_colors;

         if (T.tlength &&
@@ -219,6 +245,7 @@ int LibRaw::unpack_thumb(void)
                 T.tcolors = 1;
             }
             T.tlength = total_size;
+            THUMB_SIZE_CHECKTNZ(T.tlength);
             if (T.thumb)
               free(T.thumb);
             T.thumb = (char *)malloc(T.tlength);
@@ -254,6 +281,8 @@ int LibRaw::unpack_thumb(void)
         if (T.thumb)
           free(T.thumb);

+        THUMB_SIZE_CHECKTNZ(T.tlength);
+
         T.thumb = (char *)malloc(T.tlength);
         if (!T.tcolors)
           T.tcolors = t_colors;
@@ -278,6 +307,10 @@ int LibRaw::unpack_thumb(void)
         int i_length = T.twidth * T.theight * t_colors * 2;
         if (!T.tlength)
           T.tlength = o_length;
+        THUMB_SIZE_CHECKTNZ(o_length);
+        THUMB_SIZE_CHECKTNZ(i_length);
+        THUMB_SIZE_CHECKTNZ(T.tlength);
+
         ushort *t_thumb = (ushort *)calloc(i_length, 1);
         ID.input->read(t_thumb, 1, i_length);
         if ((libraw_internal_data.unpacker_data.order == 0x4949) ==


Adds bound check in oracle protocol

Found by oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21780

@@ -43,7 +43,7 @@ void ndpi_search_oracle(struct ndpi_detection_module_struct *ndpi_struct, struct
     NDPI_LOG_DBG2(ndpi_struct, "calculating ORACLE over tcp\n");
     /* Oracle Database 9g,10g,11g */
     if ((dport == 1521 || sport == 1521)
-	&&  (((packet->payload[0] == 0x07) && (packet->payload[1] == 0xff) && (packet->payload[2] == 0x00))
+	&&  (((packet->payload_packet_len >= 3 && packet->payload[0] == 0x07) && (packet->payload[1] == 0xff) && (packet->payload[2] == 0x00))
 	     || ((packet->payload_packet_len >= 232) && ((packet->payload[0] == 0x00) || (packet->payload[0] == 0x01))
 	     && (packet->payload[1] != 0x00)
 	     && (packet->payload[2] == 0x00)


CHANGES: snmpd: Stop reading and writing the mib_indexes/* files

Caching directory contents is something the operating system should do
and is not something Net-SNMP should do. Instead of storing a copy of
the directory contents in ${tmp_dir}/mib_indexes/${n}, always scan a
MIB directory.

@@ -201,7 +201,7 @@ SOFTWARE.
 #endif
     void            netsnmp_init_mib_internals(void);
     void            unload_all_mibs(void);
-    int             add_mibfile(const char*, const char*, FILE *);
+    int             add_mibfile(const char*, const char*);
     int             which_module(const char *);
     NETSNMP_IMPORT
     char           *module_name(int, char *);


don't mix up int and size_t (first pass to fix that)

@@ -172,7 +172,7 @@ static bcon_error_t bson_append_bcon_with_state(bson *b, const bcon *bc, bcon_st
     unsigned char doc_stack[DOC_STACK_SIZE];
     size_t doc_stack_pointer = 0;
     size_t array_index = 0;
-    unsigned int array_index_stack[ARRAY_INDEX_STACK_SIZE];
+    size_t array_index_stack[ARRAY_INDEX_STACK_SIZE];
     size_t array_index_stack_pointer = 0;
     char array_index_buffer[ARRAY_INDEX_BUFFER_SIZE]; /* max BSON size */
     int end_of_data;


net/nfc/rawsock.c: add CAP_NET_RAW check.

When creating a raw AF_NFC socket, CAP_NET_RAW needs to be checked first.

Signed-off-by: Qingyu Li <ieatmuttonchuan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

@@ -328,10 +328,13 @@ static int rawsock_create(struct net *net, struct socket *sock,
 	if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW))
 		return -ESOCKTNOSUPPORT;

-	if (sock->type == SOCK_RAW)
+	if (sock->type == SOCK_RAW) {
+		if (!capable(CAP_NET_RAW))
+			return -EPERM;
 		sock->ops = &rawsock_raw_ops;
-	else
+	} else {
 		sock->ops = &rawsock_ops;
+	}

 	sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto, kern);
 	if (!sk)


FreeBSD: Fix UNIX permissions checking

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Closes #10727

@@ -387,11 +387,34 @@ zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
 	    cr, ZFS_GROUP);
 }

+#ifdef __FreeBSD__
+uid_t
+zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
+    cred_t *cr, zfs_fuid_type_t type)
+{
+	uint32_t index = FUID_INDEX(fuid);
+
+	if (index == 0)
+		return (fuid);
+
+	return (UID_NOBODY);
+}
+#elif defined(__linux__)
+uid_t
+zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
+    cred_t *cr, zfs_fuid_type_t type)
+{
+	/*
+	 * The Linux port only supports POSIX IDs, use the passed id.
+	 */
+	return (fuid);
+}
+
+#else
 uid_t
 zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
     cred_t *cr, zfs_fuid_type_t type)
 {
-#ifdef HAVE_KSID
 	uint32_t index = FUID_INDEX(fuid);
 	const char *domain;
 	uid_t id;
@@ -410,13 +433,8 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
 		    FUID_RID(fuid), &id);
 	}
 	return (id);
-#else
-	/*
-	 * The Linux port only supports POSIX IDs, use the passed id.
-	 */
-	return (fuid);
-#endif /* HAVE_KSID */
 }
+#endif

 /*
  * Add a FUID node to the list of fuid's being created for this
@@ -559,9 +577,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
 	const char *domain;
 	char *kdomain;
 	uint32_t fuid_idx = FUID_INDEX(id);
-	uint32_t rid;
+	uint32_t rid = 0;
 	idmap_stat status;
-	uint64_t idx = 0;
+	uint64_t idx = UID_NOBODY;
 	zfs_fuid_t *zfuid = NULL;
 	zfs_fuid_info_t *fuidp = NULL;

@@ -711,9 +729,11 @@ boolean_t
 zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
 {
 #ifdef HAVE_KSID
+	uid_t		gid;
+
+#ifdef illumos
 	ksid_t		*ksid = crgetsid(cr, KSID_GROUP);
 	ksidlist_t	*ksidlist = crgetsidlist(cr);
-	uid_t		gid;

 	if (ksid && ksidlist) {
 		int		i;
@@ -746,6 +766,7 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
 			}
 		}
 	}
+#endif /* illumos */

 	/*
 	 * Not found in ksidlist, check posix groups


There is a Division by Zero in function OptimizeLayerFrames (#2743)

in file MagickCore/layer.c. cur->ticks_per_seconds can be zero
with a crafted input argument *image. This is similar to
CVE-2019-13454.

@@ -1352,11 +1352,13 @@ static Image *OptimizeLayerFrames(const Image *image,const LayerMethod method,
     if ( disposals[i] == DelDispose ) {
       size_t time = 0;
       while ( disposals[i] == DelDispose ) {
-        time += curr->delay*1000/curr->ticks_per_second;
+        time +=(size_t) (curr->delay*1000*
+          PerceptibleReciprocal((double) curr->ticks_per_second));
         curr=GetNextImageInList(curr);
         i++;
       }
-      time += curr->delay*1000/curr->ticks_per_second;
+      time += (size_t)(curr->delay*1000*
+        PerceptibleReciprocal((double) curr->ticks_per_second));
       prev_image->ticks_per_second = 100L;
       prev_image->delay = time*prev_image->ticks_per_second/1000;
     }


Merge pull request from GHSA-525h-wxcc-f66m

Signed-off-by: Ming-Wei Shih <mishih@microsoft.com>

@@ -110,7 +110,7 @@ typedef struct _oe_socket_ops
         void* buf,
         size_t len,
         int flags,
-        const struct oe_sockaddr* src_addr,
+        struct oe_sockaddr* src_addr,
         oe_socklen_t* addrlen);

     ssize_t (*sendmsg)(oe_fd_t* sock, const struct oe_msghdr* msg, int flags);


@@ -617,8 +617,7 @@ static long _syscall(
             void* buf = (void*)arg2;
             size_t len = (size_t)arg3;
             int flags = (int)arg4;
-            const struct oe_sockaddr* dest_add =
-                (const struct oe_sockaddr*)arg5;
+            struct oe_sockaddr* dest_add = (struct oe_sockaddr*)arg5;
             oe_socklen_t* addrlen = (oe_socklen_t*)arg6;

             ret = oe_recvfrom(sockfd, buf, len, flags, dest_add, addrlen);


Fix memory leak with oneofs and PB_ENABLE_MALLOC (#615)

Nanopb would leak memory when all of the following conditions were true:
- PB_ENABLE_MALLOC is defined at the compile time
- Message definitions contains an oneof field,
  the oneof contains a static submessage, and
  the static submessage contains a pointer field.
- Data being decoded contains two values for the submessage.

The logic in pb_release_union_field would detect that the same
submessage occurs twice, and wouldn't release it because keeping
the old values is necessary to match the C++ library behavior
regarding message merges.

But then decode_static_field() would go to memset() the whole
submessage to zero, because it unconditionally assumed it to
be uninitialized memory. This would normally happen when the
contents of the union field is switched to a different oneof
item, instead of merging with the same one.

This commit changes it so that the field is memset() only when
`which_field` contains a different tag.

@@ -464,14 +464,17 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
             }

         case PB_HTYPE_ONEOF:
-            *(pb_size_t*)iter->pSize = iter->pos->tag;
-            if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
+            if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE &&
+                *(pb_size_t*)iter->pSize != iter->pos->tag)
             {
                 /* We memset to zero so that any callbacks are set to NULL.
-                 * Then set any default values. */
+                 * This is because the callbacks might otherwise have values
+                 * from some other union field. */
                 memset(iter->pData, 0, iter->pos->data_size);
                 pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData);
             }
+            *(pb_size_t*)iter->pSize = iter->pos->tag;
+
             return func(stream, iter->pos, iter->pData);

         default:


CVE-2020-25646: no_log=True missing for private key content options (#125)

* Mark private key content options as no_log (CVE-2020-25646.)

* Mention no_log for openssl_privatekey's return_content option.

* Add change PR's URL.

* Plural.

@@ -152,6 +152,8 @@
             - If set to C(yes), will return the (current or generated) private key's content as I(privatekey).
             - Note that especially if the private key is not encrypted, you have to make sure that the returned
               value is treated appropriately and not accidentally written to logs etc.! Use with care!
+            - Use Ansible's I(no_log) task option to avoid the output being shown. See also
+              U(https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-keep-secret-data-in-my-playbook).
         type: bool
         default: no
         version_added: '1.0.0'


smtpd's filter state machine can prematurely release resources
leading to a crash.  From gilles@

@@ -1,4 +1,4 @@
-/*	$OpenBSD: lka_filter.c,v 1.64 2020/12/20 13:27:46 martijn Exp $	*/
+/*	$OpenBSD: lka_filter.c,v 1.65 2020/12/23 20:17:49 millert Exp $	*/

 /*
  * Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -600,11 +600,6 @@ filter_session_io(struct io *io, int evt, void *arg)
 		filter_data(fs->id, line);

 		goto nextline;
-
-	case IO_DISCONNECTED:
-		io_free(fs->io);
-		fs->io = NULL;
-		break;
 	}
 }


Check for arithmetic overflows before allocating

@@ -43,6 +43,7 @@
 #include "rpc-message.h"

 #include <assert.h>
+#include <errno.h>
 #include <string.h>

 #define ELEMS(x) (sizeof (x) / sizeof (x[0]))
@@ -114,6 +115,18 @@ p11_rpc_message_alloc_extra (p11_rpc_message *msg,
 	return (void *)(data + 1);
 }

+void *
+p11_rpc_message_alloc_extra_array (p11_rpc_message *msg,
+				   size_t nmemb,
+				   size_t size)
+{
+	if ((SIZE_MAX - sizeof (void *)) / nmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	return p11_rpc_message_alloc_extra (msg, nmemb * size);
+}
+
 bool
 p11_rpc_message_prep (p11_rpc_message *msg,
                       int call_id,


Check for result size in dst in inet_ntop

PiperOrigin-RevId: 333814318
Change-Id: Id7766ed598809f5df42d457f224d6f3dea06c224

@@ -1325,9 +1325,10 @@ const char *enc_untrusted_inet_ntop(int af, const void *src, char *dst,
     return nullptr;
   }

-  memcpy(dst, result.data(),
-         std::min(static_cast<size_t>(size),
-                  static_cast<size_t>(INET6_ADDRSTRLEN)));
+  memcpy(
+      dst, result.data(),
+      std::min({static_cast<size_t>(size), static_cast<size_t>(result.size()),
+                static_cast<size_t>(INET6_ADDRSTRLEN)}));
   return dst;
 }


@@ -615,6 +615,7 @@ struct Configurable {
   bool post302;
   bool nokeepalive; /* for keepalive needs */
   long alivetime;
+  bool content_disposition; /* use Content-disposition filename */

   int default_node_flags; /* default flags to seach for each 'node', which is
                              basically each given URL to transfer */
@@ -819,6 +820,7 @@ static void help(void)
     "    --krb <level>   Enable Kerberos with specified security level (F)",
     "    --libcurl <file> Dump libcurl equivalent code of this command line",
     "    --limit-rate <rate> Limit transfer speed to this rate",
+    " -J/--remote-header-name Use the header-provided filename (H)",
     " -l/--list-only     List only names of an FTP directory (F)",
     "    --local-port <num>[-num] Force use of these local port numbers",
     " -L/--location      Follow Location: hints (H)",
@@ -1792,6 +1794,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"i", "include",     FALSE},
     {"I", "head",        FALSE},
     {"j", "junk-session-cookies", FALSE},
+    {"J", "remote-header-name", FALSE},
     {"k", "insecure",    FALSE},
     {"K", "config",      TRUE},
     {"l", "list-only",   FALSE},
@@ -2664,6 +2667,14 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
                         &config->httpreq))
         return PARAM_BAD_USE;
       break;
+    case 'J': /* --remote-header-name */
+      if (config->include_headers) {
+        warnf(config,
+              "--include and --remote-header-name cannot be combined.\n");
+        return PARAM_BAD_USE;
+      }
+      config->content_disposition = toggle;
+      break;
     case 'k': /* allow insecure SSL connects */
       config->insecure_ok = toggle;
       break;
@@ -3314,24 +3325,41 @@ static void go_sleep(long ms)

 static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
 {
-  int res;
   size_t rc;
   struct OutStruct *out=(struct OutStruct *)stream;
   struct Configurable *config = out->config;

+  /*
+   * Once that libcurl has called back my_fwrite() the returned value
+   * is checked against the amount that was intended to be written, if
+   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+   * point returning a value different from sz*nmemb indicates failure.
+   */
+  const size_t err_rc = (sz * nmemb) ? 0 : 1;
+
   if(!out->stream) {
+    if (!out->filename) {
+      warnf(config, "Remote filename has no length!\n");
+      return err_rc; /* Failure */
+    }
+
+    if (config->content_disposition) {
+      /* don't overwrite existing files */
+      FILE* f = fopen(out->filename, "r");
+      if (f) {
+        fclose(f);
+        warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
+              strerror(EEXIST));
+        return err_rc; /* Failure */
+      }
+    }
+
     /* open file for writing */
     out->stream=fopen(out->filename, "wb");
     if(!out->stream) {
-      warnf(config, "Failed to create the file %s\n", out->filename);
-      /*
-       * Once that libcurl has called back my_fwrite() the returned value
-       * is checked against the amount that was intended to be written, if
-       * it does not match then it fails with CURLE_WRITE_ERROR. So at this
-       * point returning a value different from sz*nmemb indicates failure.
-       */
-      rc = (0 == (sz * nmemb)) ? 1 : 0;
-      return rc; /* failure */
+      warnf(config, "Failed to create the file %s: %s\n", out->filename,
+            strerror(errno));
+      return err_rc; /* failure */
     }
   }

@@ -3349,11 +3377,10 @@ static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)

   if(config->nobuffer) {
     /* disable output buffering */
-    res = fflush(out->stream);
+    int res = fflush(out->stream);
     if(res) {
       /* return a value that isn't the same as sz * nmemb */
-      rc = (0 == (sz * nmemb)) ? 1 : 0;
-      return rc; /* failure */
+      return err_rc; /* failure */
     }
   }

@@ -4049,6 +4076,87 @@ static bool stdin_upload(const char *uploadfile)
   return curlx_strequal(uploadfile, "-") || curlx_strequal(uploadfile, ".");
 }

+static char*
+parse_filename(char *ptr, int len)
+{
+  char* copy;
+  char* p;
+  char* q;
+  char quote = 0;
+
+  /* simple implementation of strndup() */
+  copy = malloc(len+1);
+  if (!copy)
+    return NULL;
+  strncpy(copy, ptr, len);
+  copy[len] = 0;
+
+  p = copy;
+  if (*p == '\'' || *p == '"') {
+    /* store the starting quote */
+    quote = *p;
+    p++;
+  }
+
+  /* if the filename contains a path, only use filename portion */
+  q = strrchr(copy, '/');
+  if (q) {
+    p=q+1;
+    if (!*p) {
+      free(copy);
+      return NULL;
+    }
+  }
+
+  q = strrchr(p, quote);
+  if (q)
+    *q = 0;
+
+  if (copy!=p)
+    memmove(copy, p, strlen(p)+1);
+
+  return copy;
+}
+
+static size_t
+header_callback(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+  struct OutStruct* outs = (struct OutStruct*)stream;
+  const char* str = (char*)ptr;
+  const size_t cb = size*nmemb;
+  const char* end = (char*)ptr + cb;
+
+  if (cb > 20 && curlx_strnequal(str, "Content-disposition:", 20)) {
+    char *p = (char*)str + 20;
+
+    /* look for the 'filename=' parameter
+       (encoded filenames (*=) are not supported) */
+    while (1) {
+      char *filename;
+
+      while (p < end && !isalpha(*p))
+        p++;
+      if (p > end-9)
+        break;
+
+      if (memcmp(p, "filename=", 9)) {
+        /* no match, find next parameter */
+        while ((p < end) && (*p != ';'))
+          p++;
+        continue;
+      }
+      p+=9;
+      filename = parse_filename(p, cb - (p - str));
+      if (filename) {
+        outs->filename = filename;
+        break;
+      }
+    }
+  }
+
+  return cb;
+}
+
 static int
 operate(struct Configurable *config, int argc, argv_item_t argv[])
 {
@@ -4431,7 +4539,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
               pc++;
               outfile = *pc ? strdup(pc): NULL;
             }
-            if(!outfile || !*outfile) {
+            if((!outfile || !*outfile) && !config->content_disposition) {
               helpf(config->errors, "Remote file name has no length!\n");
               res = CURLE_WRITE_ERROR;
               free(url);
@@ -5046,6 +5154,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         if(config->ftp_pret)
           my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);

+        if ((urlnode->flags & GETOUT_USEREMOTE)
+            && config->content_disposition) {
+          my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
+          my_setopt(curl, CURLOPT_HEADERDATA, &outs);
+        }
+
         retry_numretries = config->req_retry;

         retrystart = cutil_tvnow();
@@ -5057,6 +5171,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
             break;
           }

+          if (config->content_disposition && outs.stream && !config->mute)
+            printf("curl: Saved to filename '%s'\n", outs.filename);
+
           /* if retry-max-time is non-zero, make sure we haven't exceeded the
              time */
           if(retry_numretries &&


Curl_easy: remember last connection by id, not by pointer

CVE-2020-8231

Bug: https://curl.haxx.se/docs/CVE-2020-8231.html

Reported-by: Marc Aldorasi
Closes #5824

@@ -1300,7 +1300,7 @@ struct UrlState {
   /* buffers to store authentication data in, as parsed from input options */
   struct curltime keeps_speed; /* for the progress meter really */

-  struct connectdata *lastconnect; /* The last connection, NULL if undefined */
+  long lastconnect_id; /* The last connection, -1 if undefined */
   struct dynbuf headerb; /* buffer to store headers in */

   char *buffer; /* download buffer */


@@ -324,6 +324,8 @@ static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
   const QuantumAny range)
 {
+  if (quantum < 0)
+    return((QuantumAny) 0);
   return((QuantumAny) (((double) range*quantum)/QuantumRange+0.5));
 }


@@ -987,12 +987,12 @@ static int HistogramCompare(const void *x,const void *y)
   color_1=(const PixelInfo *) x;
   color_2=(const PixelInfo *) y;
   if (color_2->red != color_1->red)
-    return((int) color_1->red-(int) color_2->red);
+    return((int) ((ssize_t) color_1->red-(ssize_t) color_2->red));
   if (color_2->green != color_1->green)
-    return((int) color_1->green-(int) color_2->green);
+    return((int) ((ssize_t) color_1->green-(ssize_t) color_2->green));
   if (color_2->blue != color_1->blue)
-    return((int) color_1->blue-(int) color_2->blue);
-  return((int) color_2->count-(int) color_1->count);
+    return((int) ((ssize_t) color_1->blue-(ssize_t) color_2->blue));
+  return((int) ((ssize_t) color_2->count-(ssize_t) color_1->count));
 }

 #if defined(__cplusplus) || defined(c_plusplus)


virtiofsd: avoid /proc/self/fd tempdir

In order to prevent /proc/self/fd escapes a temporary directory is
created where /proc/self/fd is bind-mounted. This doesn't work on
read-only file systems.

Avoid the temporary directory by bind-mounting /proc/self/fd over /proc.
This does not affect other processes since we remounted / with MS_REC |
MS_SLAVE. /proc must exist and virtiofsd does not use it so it's safe to
do this.

Path traversal can be tested with the following function:

  static void test_proc_fd_escape(struct lo_data *lo)
  {
      int fd;
      int level = 0;
      ino_t last_ino = 0;

      fd = lo->proc_self_fd;
      for (;;) {
          struct stat st;

          if (fstat(fd, &st) != 0) {
              perror("fstat");
              return;
          }
          if (last_ino && st.st_ino == last_ino) {
              fprintf(stderr, "inode number unchanged, stopping\n");
              return;
          }
          last_ino = st.st_ino;

          fprintf(stderr, "Level %d dev %lu ino %lu\n", level,
                  (unsigned long)st.st_dev,
                  (unsigned long)last_ino);
          fd = openat(fd, "..", O_PATH | O_DIRECTORY | O_NOFOLLOW);
          level++;
      }
  }

Before and after this patch only Level 0 is displayed. Without
/proc/self/fd bind-mount protection it is possible to traverse parent
directories.

Fixes: 397ae982f4df4 ("virtiofsd: jail lo->proc_self_fd")
Cc: Miklos Szeredi <mszeredi@redhat.com>
Cc: Jens Freimann <jfreimann@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20201006095826.59813-1-stefanha@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Tested-by: Jens Freimann <jfreimann@redhat.com>
Reviewed-by: Jens Freimann <jfreimann@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

@@ -2393,8 +2393,6 @@ static void setup_wait_parent_capabilities(void)
 static void setup_namespaces(struct lo_data *lo, struct fuse_session *se)
 {
     pid_t child;
-    char template[] = "virtiofsd-XXXXXX";
-    char *tmpdir;

     /*
      * Create a new pid namespace for *child* processes.  We'll have to
@@ -2458,33 +2456,23 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se)
         exit(1);
     }

-    tmpdir = mkdtemp(template);
-    if (!tmpdir) {
-        fuse_log(FUSE_LOG_ERR, "tmpdir(%s): %m\n", template);
-        exit(1);
-    }
-
-    if (mount("/proc/self/fd", tmpdir, NULL, MS_BIND, NULL) < 0) {
-        fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, %s, MS_BIND): %m\n",
-                 tmpdir);
+    /*
+     * We only need /proc/self/fd. Prevent ".." from accessing parent
+     * directories of /proc/self/fd by bind-mounting it over /proc. Since / was
+     * previously remounted with MS_REC | MS_SLAVE this mount change only
+     * affects our process.
+     */
+    if (mount("/proc/self/fd", "/proc", NULL, MS_BIND, NULL) < 0) {
+        fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, MS_BIND): %m\n");
         exit(1);
     }

-    /* Now we can get our /proc/self/fd directory file descriptor */
-    lo->proc_self_fd = open(tmpdir, O_PATH);
+    /* Get the /proc (actually /proc/self/fd, see above) file descriptor */
+    lo->proc_self_fd = open("/proc", O_PATH);
     if (lo->proc_self_fd == -1) {
-        fuse_log(FUSE_LOG_ERR, "open(%s, O_PATH): %m\n", tmpdir);
+        fuse_log(FUSE_LOG_ERR, "open(/proc, O_PATH): %m\n");
         exit(1);
     }
-
-    if (umount2(tmpdir, MNT_DETACH) < 0) {
-        fuse_log(FUSE_LOG_ERR, "umount2(%s, MNT_DETACH): %m\n", tmpdir);
-        exit(1);
-    }
-
-    if (rmdir(tmpdir) < 0) {
-        fuse_log(FUSE_LOG_ERR, "rmdir(%s): %m\n", tmpdir);
-    }
 }

 /*


run: Convert all environment variables into bwrap arguments

This avoids some of them being filtered out by a setuid bwrap. It also
means that if they came from an untrusted source, they cannot be used
to inject arbitrary code into a non-setuid bwrap via mechanisms like
LD_PRELOAD.

Because they get bundled into a memfd or temporary file, they do not
actually appear in argv, ensuring that they remain inaccessible to
processes running under a different uid (which is important if their
values are tokens or other secrets).

Signed-off-by: Simon McVittie <smcv@collabora.com>
Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2

@@ -43,6 +43,8 @@ void          flatpak_bwrap_unset_env (FlatpakBwrap *bwrap,
                                        const char   *variable);
 void          flatpak_bwrap_add_arg (FlatpakBwrap *bwrap,
                                      const char   *arg);
+void          flatpak_bwrap_take_arg (FlatpakBwrap *bwrap,
+                                      char         *arg);
 void          flatpak_bwrap_add_noinherit_fd (FlatpakBwrap *bwrap,
                                               int           fd);
 void          flatpak_bwrap_add_fd (FlatpakBwrap *bwrap,
@@ -73,6 +75,7 @@ void          flatpak_bwrap_add_bind_arg (FlatpakBwrap *bwrap,
                                           const char   *type,
                                           const char   *src,
                                           const char   *dest);
+void          flatpak_bwrap_envp_to_args (FlatpakBwrap *bwrap);
 gboolean      flatpak_bwrap_bundle_args (FlatpakBwrap *bwrap,
                                          int           start,
                                          int           end,


Merge branch 'advisory-fix-1' CVE-2020-26262

@@ -273,6 +273,8 @@ static int good_peer_addr(turn_turnserver *server, const char* realm, ioa_addr *
 			return 0;
 		if( !*(server->allow_loopback_peers) && ioa_addr_is_loopback(peer_addr))
 			return 0;
+		if (ioa_addr_is_zero(peer_addr))
+			return 0;

 		{
 			int i;


IB/hfi1: Ensure correct mm is used at all times

Two earlier bug fixes have created a security problem in the hfi1
driver. One fix aimed to solve an issue where current->mm was not valid
when closing the hfi1 cdev. It attempted to do this by saving a cached
value of the current->mm pointer at file open time. This is a problem if
another process with access to the FD calls in via write() or ioctl() to
pin pages via the hfi driver. The other fix tried to solve a use after
free by taking a reference on the mm.

To fix this correctly we use the existing cached value of the mm in the
mmu notifier. Now we can check in the insert, evict, etc. routines that
current->mm matched what the notifier was registered for. If not, then
don't allow access. The register of the mmu notifier will save the mm
pointer.

Since in do_exit() the exit_mm() is called before exit_files(), which
would call our close routine a reference is needed on the mm. We rely on
the mmgrab done by the registration of the notifier, whereas before it was
explicit. The mmu notifier deregistration happens when the user context is
torn down, the creation of which triggered the registration.

Also of note is we do not do any explicit work to protect the interval
tree notifier. It doesn't seem that this is going to be needed since we
aren't actually doing anything with current->mm. The interval tree
notifier stuff still has a FIXME noted from a previous commit that will be
addressed in a follow on patch.

Cc: <stable@vger.kernel.org>
Fixes: e0cf75deab81 ("IB/hfi1: Fix mm_struct use after free")
Fixes: 3faa3d9a308e ("IB/hfi1: Make use of mm consistent")
Link: https://lore.kernel.org/r/20201125210112.104301.51331.stgit@awfm-01.aw.intel.com
Suggested-by: Jann Horn <jannh@google.com>
Reported-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

@@ -1,4 +1,5 @@
 /*
+ * Copyright(c) 2020 Cornelis Networks, Inc.
  * Copyright(c) 2016 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -48,23 +49,11 @@
 #include <linux/rculist.h>
 #include <linux/mmu_notifier.h>
 #include <linux/interval_tree_generic.h>
+#include <linux/sched/mm.h>

 #include "mmu_rb.h"
 #include "trace.h"

-struct mmu_rb_handler {
-	struct mmu_notifier mn;
-	struct rb_root_cached root;
-	void *ops_arg;
-	spinlock_t lock;        /* protect the RB tree */
-	struct mmu_rb_ops *ops;
-	struct mm_struct *mm;
-	struct list_head lru_list;
-	struct work_struct del_work;
-	struct list_head del_list;
-	struct workqueue_struct *wq;
-};
-
 static unsigned long mmu_node_start(struct mmu_rb_node *);
 static unsigned long mmu_node_last(struct mmu_rb_node *);
 static int mmu_notifier_range_start(struct mmu_notifier *,
@@ -92,37 +81,36 @@ static unsigned long mmu_node_last(struct mmu_rb_node *node)
 	return PAGE_ALIGN(node->addr + node->len) - 1;
 }

-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
+int hfi1_mmu_rb_register(void *ops_arg,
 			 struct mmu_rb_ops *ops,
 			 struct workqueue_struct *wq,
 			 struct mmu_rb_handler **handler)
 {
-	struct mmu_rb_handler *handlr;
+	struct mmu_rb_handler *h;
 	int ret;

-	handlr = kmalloc(sizeof(*handlr), GFP_KERNEL);
-	if (!handlr)
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
 		return -ENOMEM;

-	handlr->root = RB_ROOT_CACHED;
-	handlr->ops = ops;
-	handlr->ops_arg = ops_arg;
-	INIT_HLIST_NODE(&handlr->mn.hlist);
-	spin_lock_init(&handlr->lock);
-	handlr->mn.ops = &mn_opts;
-	handlr->mm = mm;
-	INIT_WORK(&handlr->del_work, handle_remove);
-	INIT_LIST_HEAD(&handlr->del_list);
-	INIT_LIST_HEAD(&handlr->lru_list);
-	handlr->wq = wq;
-
-	ret = mmu_notifier_register(&handlr->mn, handlr->mm);
+	h->root = RB_ROOT_CACHED;
+	h->ops = ops;
+	h->ops_arg = ops_arg;
+	INIT_HLIST_NODE(&h->mn.hlist);
+	spin_lock_init(&h->lock);
+	h->mn.ops = &mn_opts;
+	INIT_WORK(&h->del_work, handle_remove);
+	INIT_LIST_HEAD(&h->del_list);
+	INIT_LIST_HEAD(&h->lru_list);
+	h->wq = wq;
+
+	ret = mmu_notifier_register(&h->mn, current->mm);
 	if (ret) {
-		kfree(handlr);
+		kfree(h);
 		return ret;
 	}

-	*handler = handlr;
+	*handler = h;
 	return 0;
 }

@@ -134,7 +122,7 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
 	struct list_head del_list;

 	/* Unregister first so we don't get any more notifications. */
-	mmu_notifier_unregister(&handler->mn, handler->mm);
+	mmu_notifier_unregister(&handler->mn, handler->mn.mm);

 	/*
 	 * Make sure the wq delete handler is finished running.  It will not
@@ -166,6 +154,10 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
 	int ret = 0;

 	trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len);
+
+	if (current->mm != handler->mn.mm)
+		return -EPERM;
+
 	spin_lock_irqsave(&handler->lock, flags);
 	node = __mmu_rb_search(handler, mnode->addr, mnode->len);
 	if (node) {
@@ -180,6 +172,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
 		__mmu_int_rb_remove(mnode, &handler->root);
 		list_del(&mnode->list); /* remove from LRU list */
 	}
+	mnode->handler = handler;
 unlock:
 	spin_unlock_irqrestore(&handler->lock, flags);
 	return ret;
@@ -217,6 +210,9 @@ bool hfi1_mmu_rb_remove_unless_exact(struct mmu_rb_handler *handler,
 	unsigned long flags;
 	bool ret = false;

+	if (current->mm != handler->mn.mm)
+		return ret;
+
 	spin_lock_irqsave(&handler->lock, flags);
 	node = __mmu_rb_search(handler, addr, len);
 	if (node) {
@@ -239,6 +235,9 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
 	unsigned long flags;
 	bool stop = false;

+	if (current->mm != handler->mn.mm)
+		return;
+
 	INIT_LIST_HEAD(&del_list);

 	spin_lock_irqsave(&handler->lock, flags);
@@ -272,6 +271,9 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
 {
 	unsigned long flags;

+	if (current->mm != handler->mn.mm)
+		return;
+
 	/* Validity of handler and node pointers has been checked by caller. */
 	trace_hfi1_mmu_rb_remove(node->addr, node->len);
 	spin_lock_irqsave(&handler->lock, flags);


opj_t2_encode_packet(): avoid out of bound access of #1297, but likely not the proper fix

@@ -815,6 +815,15 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno,
             continue;
         }

+        /* Avoid out of bounds access of https://github.com/uclouvain/openjpeg/issues/1297 */
+        /* but likely not a proper fix. */
+        if (precno >= res->pw * res->ph) {
+            opj_event_msg(p_manager, EVT_ERROR,
+                          "opj_t2_encode_packet(): accessing precno=%u >= %u\n",
+                          precno, res->pw * res->ph);
+            return OPJ_FALSE;
+        }
+
         prc = &band->precincts[precno];
         l_nb_blocks = prc->cw * prc->ch;
         cblk = prc->cblks.enc;


Fix potential illegal memory access failures in the BFD library by ensuring that the return value from bfd_malloc() is checked before it is used.

	PR 25308
	* elf-properties.c (_bfd_elf_convert_gnu_properties): Check the
	return value from bfd_malloc.
	* elf32-arm.c (bfd_elf32_arm_vfp11_fix_veneer_locations): Likewise.
	(bfd_elf32_arm_stm32l4xx_fix_veneer_locations): Likewise.
	(elf32_arm_filter_cmse_symbols): Likewise.
	(elf32_arm_write_section): Likewise.
	* mach-o.c (bfd_mach_o_core_fetch_environment): Likewise.
	(bfd_mach_o_follow_dsym): Likewise.
	* pef.c (bfd_pef_print_loader_section): Likewise.
	(bfd_pef_scan_start_address): Likewise.
	(bfd_pef_parse_function_stubs): Likewise.
	(bfd_pef_parse_symbols): Likewise.

@@ -447,6 +447,8 @@ bfd_pef_print_loader_section (bfd *abfd, FILE *file)

   loaderlen = loadersec->size;
   loaderbuf = bfd_malloc (loaderlen);
+  if (loaderbuf == NULL)
+    return -1;

   if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0
       || bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen
@@ -478,6 +480,9 @@ bfd_pef_scan_start_address (bfd *abfd)

   loaderlen = loadersec->size;
   loaderbuf = bfd_malloc (loaderlen);
+  if (loaderbuf == NULL)
+    goto end;
+
   if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
     goto error;
   if (bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen)
@@ -753,6 +758,8 @@ bfd_pef_parse_function_stubs (bfd *abfd,
     (header.imported_library_count * sizeof (bfd_pef_imported_library));
   imports = bfd_malloc
     (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol));
+  if (libraries == NULL || imports == NULL)
+    goto error;

   if (loaderlen < (56 + (header.imported_library_count * 24)))
     goto error;
@@ -897,6 +904,8 @@ bfd_pef_parse_symbols (bfd *abfd, asymbol **csym)
     {
       codelen = codesec->size;
       codebuf = bfd_malloc (codelen);
+      if (codebuf == NULL)
+	goto end;
       if (bfd_seek (abfd, codesec->filepos, SEEK_SET) < 0)
 	goto end;
       if (bfd_bread ((void *) codebuf, codelen, abfd) != codelen)
@@ -908,6 +917,8 @@ bfd_pef_parse_symbols (bfd *abfd, asymbol **csym)
     {
       loaderlen = loadersec->size;
       loaderbuf = bfd_malloc (loaderlen);
+      if (loaderbuf == NULL)
+	goto end;
       if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
 	goto end;
       if (bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen)


Fix potential illegal memory access when parsing a corrupt PEF format file.

	PR 25307
	(bfd_pef_parse_function_stubs): Correct the test that ensures that
	there is enough data remaining in the code buffer before
	attempting to read a function stub.

@@ -806,7 +806,7 @@ bfd_pef_parse_function_stubs (bfd *abfd,
 	  codepos += 4;
 	}

-      if ((codepos + 4) > codelen)
+      if ((codepos + 24) > codelen)
 	break;

       ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &sym_index);


FAPI: Fix execution of policy callback for reading PCR registers.

For Policy PCR current PCR registers of the TPM registers can be used to compute
the policy digest. The counter in the computed PCR list was not set. Thus a empty
PCR list was used for the policy digest computation.

Signed-off-by: Juergen Repp <juergen.repp@sit.fraunhofer.de>

@@ -373,6 +373,7 @@ ifapi_read_pcr(

         /* Initialize digest list with pcr values from TPM */
         i_pcr = 0;
+        (*pcr_values)->count = pcr_digests->count;
         for (i = 0; i < out_selection->count; i++) {
             for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
                 uint8_t byte_idx = pcr / 8;


@@ -1,6 +1,6 @@
 /*
  *   stunnel       TLS offloading and load-balancing proxy
- *   Copyright (C) 1998-2019 Michal Trojnara <Michal.Trojnara@stunnel.org>
+ *   Copyright (C) 1998-2020 Michal Trojnara <Michal.Trojnara@stunnel.org>
  *
  *   This program is free software; you can redistribute it and/or modify it
  *   under the terms of the GNU General Public License as published by the


@@ -1,6 +1,6 @@
 /*
  *   stunnel       TLS offloading and load-balancing proxy
- *   Copyright (C) 1998-2019 Michal Trojnara <Michal.Trojnara@stunnel.org>
+ *   Copyright (C) 1998-2020 Michal Trojnara <Michal.Trojnara@stunnel.org>
  *
  *   This program is free software; you can redistribute it and/or modify it
  *   under the terms of the GNU General Public License as published by the
@@ -65,7 +65,7 @@

 /* START CUSTOMIZE */
 #define VERSION_MAJOR 5
-#define VERSION_MINOR 56
+#define VERSION_MINOR 57
 /* END CUSTOMIZE */

 /* all the following macros are ABSOLUTELY NECESSARY to have proper string


Merge branch '2021-02-15-fix-CVE-2021-27097-CVE-2021-27138'

Fix CVE-2021-27097 and CVE-2021-27138.  For more details see
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27097 and
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27138

@@ -114,7 +114,7 @@ int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc,
 	/* This cannot be done earlier,
 	 * we need complete FIT image in RAM first */
 	if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
-		if (!fit_check_format(fit_hdr)) {
+		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 			bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
 			puts("** Bad FIT image format\n");
 			return 1;


@@ -286,7 +286,7 @@ int update_tftp(ulong addr, char *interface, char *devstring)
 got_update_file:
 	fit = map_sysmem(addr, 0);

-	if (!fit_check_format((void *)fit)) {
+	if (fit_check_format((void *)fit, IMAGE_SIZE_INVAL)) {
 		printf("Bad FIT format of the update file, aborting "
 							"auto-update\n");
 		return 1;
@@ -363,7 +363,7 @@ int fit_update(const void *fit)
 	if (!fit)
 		return -EINVAL;

-	if (!fit_check_format((void *)fit)) {
+	if (fit_check_format((void *)fit, IMAGE_SIZE_INVAL)) {
 		printf("Bad FIT format of the update file, aborting auto-update\n");
 		return -EINVAL;
 	}


@@ -26,7 +26,8 @@
 int fit_verify_header(unsigned char *ptr, int image_size,
 			struct image_tool_params *params)
 {
-	if (fdt_check_header(ptr) != EXIT_SUCCESS || !fit_check_format(ptr))
+	if (fdt_check_header(ptr) != EXIT_SUCCESS ||
+	    fit_check_format(ptr, IMAGE_SIZE_INVAL))
 		return EXIT_FAILURE;

 	return EXIT_SUCCESS;


@@ -292,7 +292,7 @@ static int image_info(ulong addr)
 	case IMAGE_FORMAT_FIT:
 		puts("   FIT image found\n");

-		if (!fit_check_format(hdr)) {
+		if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
 			puts("Bad FIT image format!\n");
 			unmap_sysmem(hdr);
 			return 1;
@@ -369,7 +369,7 @@ static int do_imls_nor(void)
 #endif
 #if defined(CONFIG_FIT)
 			case IMAGE_FORMAT_FIT:
-				if (!fit_check_format(hdr))
+				if (fit_check_format(hdr, IMAGE_SIZE_INVAL))
 					goto next_sector;

 				printf("FIT Image at %08lX:\n", (ulong)hdr);
@@ -449,7 +449,7 @@ static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
 		return ret;
 	}

-	if (!fit_check_format(imgdata)) {
+	if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) {
 		free(imgdata);
 		return 0;
 	}


@@ -337,10 +337,10 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr)
 	if (res < 0)
 		return res;

-	res = fit_check_format(fit_header);
-	if (!res) {
+	res = fit_check_format(fit_header, IMAGE_SIZE_INVAL);
+	if (res) {
 		debug("Could not find valid FIT image\n");
-		return -EINVAL;
+		return res;
 	}

 	/* Get the splash image node */


@@ -376,12 +376,12 @@ def manipulate(root, strblock):
     """
     Maliciously manipulates the structure to create a crafted FIT file
     """
-    # locate /images/kernel@1 (frankly, it just expects it to be the first one)
+    # locate /images/kernel-1 (frankly, it just expects it to be the first one)
     kernel_node = root[0][0]
     # clone it to save time filling all the properties
     fake_kernel = kernel_node.clone()
     # rename the node
-    fake_kernel.name = b'kernel@2'
+    fake_kernel.name = b'kernel-2'
     # get rid of signatures/hashes
     fake_kernel.children = []
     # NOTE: this simply replaces the first prop... either description or data
@@ -391,13 +391,13 @@ def manipulate(root, strblock):
     root[0].children.append(fake_kernel)

     # modify the default configuration
-    root[1].props[0].value = b'conf@2\x00'
+    root[1].props[0].value = b'conf-2\x00'
     # clone the first (only?) configuration
     fake_conf = root[1][0].clone()
     # rename and change kernel and fdt properties to select the crafted kernel
-    fake_conf.name = b'conf@2'
-    fake_conf.props[0].value = b'kernel@2\x00'
-    fake_conf.props[1].value = b'fdt@1\x00'
+    fake_conf.name = b'conf-2'
+    fake_conf.props[0].value = b'kernel-2\x00'
+    fake_conf.props[1].value = b'fdt-1\x00'
     # insert the new configuration under /configurations
     root[1].children.append(fake_conf)


Merge pull request #110 from lemenkov/HKUST-CVEs

HKUST CVEs

@@ -25,11 +25,11 @@
 #include <math.h>
 #include <stdio.h>
 #include <time.h>
-#include "xstd.h"
 #include "logreport.h"
 #include "types.h"
 #include "bitmap.h"
 #include "despeckle.h"
+#include <glib.h>

 /* Calculate Error - compute the error between two colors
  *
@@ -578,7 +578,7 @@ static void despeckle_iteration( /* in */ int level,
   current_size = 1 << level;
   tightness = (int)(noise_max / (1.0 + adaptive_tightness * level));

-  mask = (unsigned char *)calloc(width * height, sizeof(unsigned char));
+  mask = g_malloc0((gsize)width * height * sizeof(unsigned char));
   for (y = 0; y < height; y++) {
     for (x = 0; x < width; x++) {
       if (mask[y * width + x] == 0) {
@@ -597,7 +597,7 @@ static void despeckle_iteration( /* in */ int level,
     }
   }

-  free(mask);
+  g_free(mask);
 }

 /* Despeckle Iteration - Despeckle all regions smaller than cur_size pixels
@@ -627,7 +627,7 @@ static void despeckle_iteration_8( /* in */ int level,
   current_size = 1 << level;
   tightness = (int)(noise_max / (1.0 + adaptive_tightness * level));

-  mask = (unsigned char *)calloc(width * height, sizeof(unsigned char));
+  mask = g_malloc0((gsize)width * height * sizeof(unsigned char));
   for (y = 0; y < height; y++) {
     for (x = 0; x < width; x++) {
       if (mask[y * width + x] == 0) {
@@ -646,7 +646,7 @@ static void despeckle_iteration_8( /* in */ int level,
     }
   }

-  free(mask);
+  g_free(mask);
 }

 /* Despeckle - Despeckle a 8 or 24 bit image


@@ -25,7 +25,6 @@
 #include "autotrace.h"
 #include "private.h"
 #include "input.h"
-#include "xstd.h"
 #include "filename.h"
 #include <string.h>
 #include <glib.h>
@@ -173,7 +172,7 @@ const char **at_input_list_new(void)

 void at_input_list_free(const char **list)
 {
-  free((char **)list);
+  g_free((char **)list);
 }

 char *at_input_shortlist(void)


@@ -22,7 +22,7 @@
 #endif /* Def: HAVE_CONFIG_H */

 #include "output-fig.h"
-#include "xstd.h"
+#include <glib.h>
 #include "logreport.h"
 #include "color.h"
 #include "spline.h"
@@ -152,7 +152,7 @@ static void out_fig_splines(FILE * file, spline_list_array_type shape, int llx,
 */

   /*  Need to create hash table for colours */
-  XMALLOC(spline_colours, (sizeof(int) * SPLINE_LIST_ARRAY_LENGTH(shape)));
+  spline_colours = g_malloc(sizeof(int) * SPLINE_LIST_ARRAY_LENGTH(shape));

   /* Preload the big 8 */
   fig_col_init();
@@ -185,9 +185,9 @@ static void out_fig_splines(FILE * file, spline_list_array_type shape, int llx,
     int pointcount = 0, is_spline = 0, j;
     int maxlength = SPLINE_LIST_LENGTH(list) * 5 + 1;

-    XMALLOC(pointx, maxlength * sizeof(int));
-    XMALLOC(pointy, maxlength * sizeof(int));
-    XMALLOC(contrl, maxlength * sizeof(gfloat));
+    pointx = g_malloc(maxlength * sizeof(int));
+    pointy = g_malloc(maxlength * sizeof(int));
+    contrl = g_malloc(maxlength * sizeof(gfloat));

     if (list.clockwise) {
       fig_colour = FIG_WHITE;
@@ -339,11 +339,11 @@ static void out_fig_splines(FILE * file, spline_list_array_type shape, int llx,
     if (fig_depth < 0) {
       fig_depth = 0;
     }
-    free(pointx);
-    free(pointy);
-    free(contrl);
+    g_free(pointx);
+    g_free(pointy);
+    g_free(contrl);
   }
-  free(spline_colours);
+  g_free(spline_colours);
   return;
 }


@@ -1,85 +0,0 @@
-/* xstd.h: Wrappers for functions in C standard library
- Was: xmem, xfile */
-
-/* These call the corresponding function in the standard library, and
-   abort if those routines fail. */
-
-#ifndef XSTD_H
-#define XSTD_H
-
-#include "types.h"
-#include <assert.h>
-#include <stdlib.h>
-
-/*
- * XMEM
- */
-#ifndef __cplusplus
-#define XMALLOC(new_mem, size)			\
-do						\
-  {						\
-    assert(size);                               \
-    new_mem = (gpointer) malloc (size);	\
-    assert(new_mem);				\
-  } while (0)
-
-#define XCALLOC(new_mem, size)			\
-do						\
-  {						\
-    assert(size);                               \
-    new_mem = (gpointer) calloc (size, 1);	\
-    assert(new_mem);				\
-  } while (0)
-
-#define XREALLOC(old_ptr, size)				\
-do							\
-  {							\
-    gpointer new_mem;					\
-							\
-    if (old_ptr == NULL)				\
-      XMALLOC (new_mem, size);				\
-    else						\
-      {							\
-        new_mem = (gpointer) realloc (old_ptr, size);	\
-        assert(new_mem);				\
-      }							\
-							\
-    old_ptr = new_mem;					\
-} while (0)
-
-#else
-/* Use templates if Cplusplus... */
-#define XMALLOC(new_mem, size)					\
-do								\
-  {								\
-    assert(size);                                               \
-    (gpointer&)(new_mem) = (gpointer) malloc (size);	\
-     assert(new_mem);						\
-  } while (0)
-
-#define XCALLOC(new_mem, sizex)					\
-do								\
-  {								\
-    assert(sizex);                                              \
-    (gpointer&)(new_mem) = (void *) calloc (sizex, 1);	\
-    assert(new_mem);						\
-  } while (0)
-
-#define XREALLOC(old_ptr, size)						  \
-do									  \
-  {									  \
-    gpointer new_mem;							  \
-									  \
-    if (old_ptr == NULL)						  \
-      XMALLOC (new_mem, (size));					  \
-    else								  \
-      {									  \
-        (gpointer&) new_mem = (gpointer) realloc ((old_ptr), (size)); \
-        assert(new_mem);						  \
-      }									  \
-									  \
-    (gpointer&)old_ptr = new_mem;					  \
-  } while (0)
-#endif
-
-#endif /* Not XSTD_H */


@@ -30,6 +30,7 @@
 #include "input-gf.h"
 #include "output-ugs.h"
 #include "bitmap.h"
+#include <glib.h>

 #define WHITE		0

@@ -267,7 +268,7 @@ static void get_character_bitmap(gf_char_t * sym)

   sym->height = height;
   sym->width = width;
-  sym->bitmap = calloc(width, height);
+  sym->bitmap = g_malloc0((gsize)width * height);
   if (!sym->bitmap) {
     fprintf(stderr, "%s: out of memory\n", sym->font->input_filename);
     exit(-1);
@@ -445,7 +446,7 @@ static void deblank(gf_char_t * sym)
     } else {
       condensed.width = sym->width - white_on_left - white_on_right;
       condensed.height = sym->height - white_on_top - white_on_bottom;
-      condensed.bitmap = calloc(condensed.width, condensed.height);
+      condensed.bitmap = g_malloc0((gsize)condensed.width * condensed.height);
       if (!condensed.bitmap) {
         fprintf(stderr, "%s: out of memory\n", sym->font->input_filename);
         exit(-1);
@@ -459,7 +460,7 @@ static void deblank(gf_char_t * sym)
       sym->bbox_min_col += white_on_left;
       sym->bbox_max_col -= white_on_right;
     }
-    free(sym->bitmap);
+    g_free(sym->bitmap);
     sym->bitmap = condensed.bitmap;
   }
 }
@@ -679,7 +680,7 @@ at_bitmap input_gf_reader(gchar * filename, at_input_opts_type * opts, at_msg_fu
       AT_BITMAP_BITS(&bitmap)[ptr++] = PIXEL(sym, j, i);
     }
   }
-  free(sym->bitmap);
+  g_free(sym->bitmap);
   fclose(font->input_file);
   return bitmap;
 }