TCP's window scale factor is determined at the connection start-up. Among other things local memory constraints are checked and used as the basis to calculate the window scale shift factor. The exact procedure is complex and not of interest here. Currently the Linux network stack does not consider a reduced rcv buffer which can be reduced via setsockopt(). Today I sent a patch which fix this with some lines of code:

if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
        (req->window_clamp > tcp_full_space(sk) || req->window_clamp == 0))
    req->window_clamp = tcp_full_space(sk);

I waive explaining text in the patch why I fixed the bug in this way and not modified the main function (tcp_select_initial_window()) and hope that Dave and Ilpo trust me ... ;-)