Whether param will still be in the backward graph of mult will depend on the specifics of the model. For example if we had a linear model, grad of outputs wrt to parameters, is just your model inputs * grad_output, i.e., its not a function of the weight.
But the custom model I defined here is an example of one that does work because the partial derivative of X * k**2 wrt k is still 2 * X * k
import torch
import torch.nn as nn

model_type = "custom"

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.k = nn.Parameter(torch.rand(1))
    def forward(self, X):
        # the reason we need to clone here is because
        # if an optimizer updates k in-place in no-grad mode it would increment the
        # k's version counter, which could be an issue if k is saved for backward 
        return X * self.k.clone() ** 2

X = torch.rand(10, requires_grad=True).clone()

if model_type == "linear":
    model = nn.Linear(10, 10)
elif model_type == "custom":
    model = Model()

y_hat = model(X).sum()
eta = [torch.rand_like(t, requires_grad=True) for t in model.parameters()]
param_grads = torch.autograd.grad(y_hat, model.parameters(), create_graph=True)
out = torch.max(torch.stack([torch.dot(x.flatten(), y.flatten()) for (x, y) in zip(param_grads, eta)]))

if model_type == "linear":
    # d_out_d_params = torch.autograd.grad(out, model.parameters())
    # RuntimeError: One of the differentiated Tensors appears to not have been used in the graph
    pass
elif model_type == "custom":
    d_out_d_params = torch.autograd.grad(out, model.parameters())
    print(d_out_d_params)